Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.core; | 5 part of dart.core; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The [Iterable] interface allows to get an [Iterator] out of an | 8 * The [Iterable] interface allows to get an [Iterator] out of an |
| 9 * [Iterable] object. | 9 * [Iterable] object. |
| 10 * | 10 * |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 /** | 41 /** |
| 42 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced | 42 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced |
| 43 * by the result of [:f(e):]. | 43 * by the result of [:f(e):]. |
| 44 * | 44 * |
| 45 * This method returns a view of the mapped elements. As long as the | 45 * This method returns a view of the mapped elements. As long as the |
| 46 * returned [Iterable] is not iterated over, the supplied function [f] will | 46 * returned [Iterable] is not iterated over, the supplied function [f] will |
| 47 * not be invoked. The transformed elements will not be cached. Iterating | 47 * not be invoked. The transformed elements will not be cached. Iterating |
| 48 * multiple times over the the returned [Iterable] will invoke the supplied | 48 * multiple times over the the returned [Iterable] will invoke the supplied |
| 49 * function [f] multiple times on the same element. | 49 * function [f] multiple times on the same element. |
| 50 */ | 50 */ |
| 51 Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); | 51 Iterable map(f(E element)); |
| 52 | 52 |
| 53 /** | 53 /** |
| 54 * Returns a lazy [Iterable] with all elements that satisfy the | 54 * Returns a lazy [Iterable] with all elements that satisfy the |
| 55 * predicate [f]. | 55 * predicate [f]. |
| 56 * | 56 * |
| 57 * This method returns a view of the mapped elements. As long as the | 57 * This method returns a view of the mapped elements. As long as the |
| 58 * returned [Iterable] is not iterated over, the supplied function [f] will | 58 * returned [Iterable] is not iterated over, the supplied function [f] will |
| 59 * not be invoked. Iterating will not cache results, and thus iterating | 59 * not be invoked. Iterating will not cache results, and thus iterating |
| 60 * multiple times over the the returned [Iterable] will invoke the supplied | 60 * multiple times over the the returned [Iterable] will invoke the supplied |
| 61 * function [f] multiple times on the same element. | 61 * function [f] multiple times on the same element. |
| 62 */ | 62 */ |
| 63 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); | 63 Iterable<E> where(bool f(E element)); |
| 64 | |
| 65 | 64 |
| 66 /** | 65 /** |
| 67 * Expand each element of this [Iterable] into zero or more elements. | 66 * Expand each element of this [Iterable] into zero or more elements. |
| 68 * | 67 * |
| 69 * The resulting Iterable will run through the elements returned | 68 * The resulting Iterable will run through the elements returned |
| 70 * by [f] for each element of this, in order. | 69 * by [f] for each element of this, in order. |
| 71 * | 70 * |
| 72 * The returned [Iterable] is lazy, and will call [f] for each element | 71 * The returned [Iterable] is lazy, and will call [f] for each element |
| 73 * of this every time it's iterated. | 72 * of this every time it's iterated. |
| 74 */ | 73 */ |
| 75 Iterable expand(Iterable f(E element)) => | 74 Iterable expand(Iterable f(E element)); |
| 76 new ExpandIterable<E, dynamic>(this, f); | |
| 77 | 75 |
| 78 /** | 76 /** |
| 79 * Check whether the collection contains an element equal to [element]. | 77 * Check whether the collection contains an element equal to [element]. |
| 80 */ | 78 */ |
| 81 bool contains(E element) { | 79 bool contains(E element); |
| 82 for (E e in this) { | |
| 83 if (e == element) return true; | |
| 84 } | |
| 85 return false; | |
| 86 } | |
| 87 | 80 |
| 88 /** | 81 /** |
| 89 * Applies the function [f] to each element of this collection. | 82 * Applies the function [f] to each element of this collection. |
| 90 */ | 83 */ |
| 91 void forEach(void f(E element)) { | 84 void forEach(void f(E element)); |
| 92 for (E element in this) f(element); | |
| 93 } | |
| 94 | 85 |
| 95 /** | 86 /** |
| 96 * Reduce a collection to a single value by iteratively combining elements | 87 * Reduce a collection to a single value by iteratively combining elements |
| 97 * of the collection using the provided function. | 88 * of the collection using the provided function. |
| 98 * | 89 * |
| 99 * Example of calculating the sum of an iterable: | 90 * Example of calculating the sum of an iterable: |
| 100 * | 91 * |
| 101 * iterable.reduce((value, element) => value + element); | 92 * iterable.reduce((value, element) => value + element); |
| 102 * | 93 * |
| 103 */ | 94 */ |
| 104 E reduce(E combine(E value, E element)) { | 95 E reduce(E combine(E value, E element)); |
| 105 Iterator<E> iterator = this.iterator; | |
| 106 if (!iterator.moveNext()) { | |
| 107 throw new StateError("No elements"); | |
| 108 } | |
| 109 E value = iterator.current; | |
| 110 while (iterator.moveNext()) { | |
| 111 value = combine(value, iterator.current); | |
| 112 } | |
| 113 return value; | |
| 114 } | |
| 115 | 96 |
| 116 /** | 97 /** |
| 117 * Reduce a collection to a single value by iteratively combining each element | 98 * Reduce a collection to a single value by iteratively combining each element |
|
floitsch
2013/04/11 14:24:57
Reduces
Lasse Reichstein Nielsen
2013/04/15 14:19:50
Done.
| |
| 118 * of the collection with an existing value using the provided function. | 99 * of the collection with an existing value using the provided function. |
| 119 * Use [initialValue] as the initial value, and the function [combine] to | 100 * Use [initialValue] as the initial value, and the function [combine] to |
| 120 * create a new value from the previous one and an element. | 101 * create a new value from the previous one and an element. |
| 121 * | 102 * |
| 122 * Example of calculating the sum of an iterable: | 103 * Example of calculating the sum of an iterable: |
| 123 * | 104 * |
| 124 * iterable.fold(0, (prev, element) => prev + element); | 105 * iterable.fold(0, (prev, element) => prev + element); |
| 125 * | 106 * |
| 126 */ | 107 */ |
| 127 dynamic fold(var initialValue, | 108 dynamic fold(var initialValue, |
| 128 dynamic combine(var previousValue, E element)) { | 109 dynamic combine(var previousValue, E element)); |
| 129 var value = initialValue; | |
| 130 for (E element in this) value = combine(value, element); | |
| 131 return value; | |
| 132 } | |
| 133 | 110 |
| 134 /** | 111 /** |
| 135 * Returns true if every elements of this collection satisify the | 112 * Returns true if every elements of this collection satisify the |
| 136 * predicate [f]. Returns false otherwise. | 113 * predicate [f]. Returns false otherwise. |
| 137 */ | 114 */ |
| 138 bool every(bool f(E element)) { | 115 bool every(bool f(E element)); |
| 139 for (E element in this) { | |
| 140 if (!f(element)) return false; | |
| 141 } | |
| 142 return true; | |
| 143 } | |
| 144 | 116 |
| 145 /** | 117 /** |
| 146 * Convert each element to a [String] and concatenate the strings. | 118 * Convert each element to a [String] and concatenate the strings. |
|
floitsch
2013/04/11 14:24:57
Converts ... concatenates ...
Lasse Reichstein Nielsen
2013/04/15 14:19:50
Done.
| |
| 147 * | 119 * |
| 148 * Converts each element to a [String] by calling [Object.toString] on it. | 120 * Converts each element to a [String] by calling [Object.toString] on it. |
| 149 * Then concatenates the strings, optionally separated by the [separator] | 121 * Then concatenates the strings, optionally separated by the [separator] |
| 150 * string. | 122 * string. |
| 151 */ | 123 */ |
| 152 String join([String separator = ""]) { | 124 String join([String separator = ""]) { |
| 153 StringBuffer buffer = new StringBuffer(); | 125 StringBuffer buffer = new StringBuffer(); |
| 154 buffer.writeAll(this, separator); | 126 buffer.writeAll(this, separator); |
| 155 return buffer.toString(); | 127 return buffer.toString(); |
| 156 } | 128 } |
| 157 | 129 |
| 158 /** | 130 /** |
| 159 * Returns true if one element of this collection satisfies the | 131 * Returns true if one element of this collection satisfies the |
| 160 * predicate [f]. Returns false otherwise. | 132 * predicate [f]. Returns false otherwise. |
| 161 */ | 133 */ |
| 162 bool any(bool f(E element)) { | 134 bool any(bool f(E element)); |
| 163 for (E element in this) { | |
| 164 if (f(element)) return true; | |
| 165 } | |
| 166 return false; | |
| 167 } | |
| 168 | 135 |
| 169 List<E> toList({ bool growable: true }) => | 136 /** |
| 170 new List<E>.from(this, growable: growable); | 137 * Create a [List] containing the elements of this [Iterable]. |
|
floitsch
2013/04/11 14:24:57
Creates
Lasse Reichstein Nielsen
2013/04/15 14:19:50
Done.
| |
| 171 Set<E> toSet() => new Set<E>.from(this); | 138 * |
| 139 * The elements will be in iteration order. The list is fixed-length | |
| 140 * if [growable] is false. | |
| 141 */ | |
| 142 List<E> toList({ bool growable: true }); | |
| 143 | |
| 144 /** | |
| 145 * Create a [Set] containing the elements of this [Iterable]. | |
|
floitsch
2013/04/11 14:24:57
Creates
Lasse Reichstein Nielsen
2013/04/15 14:19:50
Done.
| |
| 146 */ | |
| 147 Set<E> toSet(); | |
| 172 | 148 |
| 173 /** | 149 /** |
| 174 * Returns the number of elements in [this]. | 150 * Returns the number of elements in [this]. |
| 175 * | 151 * |
| 176 * Counting all elements may be involve running through all elements and can | 152 * Counting all elements may be involve running through all elements and can |
| 177 * therefore be slow. | 153 * therefore be slow. |
| 178 */ | 154 */ |
| 179 int get length { | 155 int get length; |
| 180 int count = 0; | |
| 181 Iterator it = iterator; | |
| 182 while (it.moveNext()) { | |
| 183 count++; | |
| 184 } | |
| 185 return count; | |
| 186 } | |
| 187 | 156 |
| 188 /** | 157 /** |
| 189 * Returns true if there is no element in this collection. | 158 * Returns true if there is no element in this collection. |
| 190 */ | 159 */ |
| 191 bool get isEmpty => !iterator.moveNext(); | 160 bool get isEmpty; |
| 192 | 161 |
| 193 /** | 162 /** |
| 194 * Returns an [Iterable] with at most [n] elements. | 163 * Returns an [Iterable] with at most [n] elements. |
| 195 * | 164 * |
| 196 * The returned [Iterable] may contain fewer than [n] elements, if [this] | 165 * The returned [Iterable] may contain fewer than [n] elements, if [this] |
| 197 * contains fewer than [n] elements. | 166 * contains fewer than [n] elements. |
| 198 */ | 167 */ |
| 199 Iterable<E> take(int n) { | 168 Iterable<E> take(int n); |
| 200 return new TakeIterable<E>(this, n); | |
| 201 } | |
| 202 | 169 |
| 203 /** | 170 /** |
| 204 * Returns an [Iterable] that stops once [test] is not satisfied anymore. | 171 * Returns an [Iterable] that stops once [test] is not satisfied anymore. |
| 205 * | 172 * |
| 206 * The filtering happens lazily. Every new [Iterator] of the returned | 173 * The filtering happens lazily. Every new [Iterator] of the returned |
| 207 * [Iterable] will start iterating over the elements of [this]. | 174 * [Iterable] will start iterating over the elements of [this]. |
| 208 * When the iterator encounters an element [:e:] that does not satisfy [test], | 175 * When the iterator encounters an element [:e:] that does not satisfy [test], |
| 209 * it discards [:e:] and moves into the finished state. That is, it will not | 176 * it discards [:e:] and moves into the finished state. That is, it will not |
| 210 * ask or provide any more elements. | 177 * ask or provide any more elements. |
| 211 */ | 178 */ |
| 212 Iterable<E> takeWhile(bool test(E value)) { | 179 Iterable<E> takeWhile(bool test(E value)); |
| 213 return new TakeWhileIterable<E>(this, test); | |
| 214 } | |
| 215 | 180 |
| 216 /** | 181 /** |
| 217 * Returns an [Iterable] that skips the first [n] elements. | 182 * Returns an [Iterable] that skips the first [n] elements. |
| 218 * | 183 * |
| 219 * If [this] has fewer than [n] elements, then the resulting [Iterable] will | 184 * If [this] has fewer than [n] elements, then the resulting [Iterable] will |
| 220 * be empty. | 185 * be empty. |
| 221 */ | 186 */ |
| 222 Iterable<E> skip(int n) { | 187 Iterable<E> skip(int n); |
| 223 return new SkipIterable<E>(this, n); | |
| 224 } | |
| 225 | 188 |
| 226 /** | 189 /** |
| 227 * Returns an [Iterable] that skips elements while [test] is satisfied. | 190 * Returns an [Iterable] that skips elements while [test] is satisfied. |
| 228 * | 191 * |
| 229 * The filtering happens lazily. Every new [Iterator] of the returned | 192 * The filtering happens lazily. Every new [Iterator] of the returned |
| 230 * [Iterable] will iterate over all elements of [this]. | 193 * [Iterable] will iterate over all elements of [this]. |
| 231 * As long as the iterator's elements do not satisfy [test] they are | 194 * As long as the iterator's elements do not satisfy [test] they are |
| 232 * discarded. Once an element satisfies the [test] the iterator stops testing | 195 * discarded. Once an element satisfies the [test] the iterator stops testing |
| 233 * and uses every element unconditionally. | 196 * and uses every element unconditionally. |
| 234 */ | 197 */ |
| 235 Iterable<E> skipWhile(bool test(E value)) { | 198 Iterable<E> skipWhile(bool test(E value)); |
| 236 return new SkipWhileIterable<E>(this, test); | |
| 237 } | |
| 238 | 199 |
| 239 /** | 200 /** |
| 240 * Returns the first element. | 201 * Returns the first element. |
| 241 * | 202 * |
| 242 * If [this] is empty throws a [StateError]. Otherwise this method is | 203 * If [this] is empty throws a [StateError]. Otherwise this method is |
| 243 * equivalent to [:this.elementAt(0):] | 204 * equivalent to [:this.elementAt(0):] |
| 244 */ | 205 */ |
| 245 E get first { | 206 E get first; |
| 246 Iterator it = iterator; | |
| 247 if (!it.moveNext()) { | |
| 248 throw new StateError("No elements"); | |
| 249 } | |
| 250 return it.current; | |
| 251 } | |
| 252 | 207 |
| 253 /** | 208 /** |
| 254 * Returns the last element. | 209 * Returns the last element. |
| 255 * | 210 * |
| 256 * If [this] is empty throws a [StateError]. | 211 * If [this] is empty throws a [StateError]. |
| 257 */ | 212 */ |
| 258 E get last { | 213 E get last; |
| 259 Iterator it = iterator; | |
| 260 if (!it.moveNext()) { | |
| 261 throw new StateError("No elements"); | |
| 262 } | |
| 263 E result; | |
| 264 do { | |
| 265 result = it.current; | |
| 266 } while(it.moveNext()); | |
| 267 return result; | |
| 268 } | |
| 269 | 214 |
| 270 /** | 215 /** |
| 271 * Returns the single element in [this]. | 216 * Returns the single element in [this]. |
| 272 * | 217 * |
| 273 * If [this] is empty or has more than one element throws a [StateError]. | 218 * If [this] is empty or has more than one element throws a [StateError]. |
| 274 */ | 219 */ |
| 275 E get single { | 220 E get single; |
| 276 Iterator it = iterator; | |
| 277 if (!it.moveNext()) throw new StateError("No elements"); | |
| 278 E result = it.current; | |
| 279 if (it.moveNext()) throw new StateError("More than one element"); | |
| 280 return result; | |
| 281 } | |
| 282 | 221 |
| 283 /** | 222 /** |
| 284 * Returns the first element that satisfies the given predicate [f]. | 223 * Returns the first element that satisfies the given predicate [f]. |
| 285 * | 224 * |
| 286 * If none matches, the result of invoking the [orElse] function is | 225 * If none matches, the result of invoking the [orElse] function is |
| 287 * returned. By default, when [orElse] is `null`, a [StateError] is | 226 * returned. By default, when [orElse] is `null`, a [StateError] is |
| 288 * thrown. | 227 * thrown. |
| 289 */ | 228 */ |
| 290 E firstWhere(bool test(E value), { E orElse() }) { | 229 E firstWhere(bool test(E value), { E orElse() }); |
| 291 // TODO(floitsch): check that arguments are of correct type? | |
| 292 for (E element in this) { | |
| 293 if (test(element)) return element; | |
| 294 } | |
| 295 if (orElse != null) return orElse(); | |
| 296 throw new StateError("No matching element"); | |
| 297 } | |
| 298 | 230 |
| 299 /** | 231 /** |
| 300 * Returns the last element that satisfies the given predicate [f]. | 232 * Returns the last element that satisfies the given predicate [f]. |
| 301 * | 233 * |
| 302 * If none matches, the result of invoking the [orElse] function is | 234 * If none matches, the result of invoking the [orElse] function is |
| 303 * returned. By default, when [orElse] is [:null:], a [StateError] is | 235 * returned. By default, when [orElse] is [:null:], a [StateError] is |
| 304 * thrown. | 236 * thrown. |
| 305 */ | 237 */ |
| 306 E lastWhere(bool test(E value), {E orElse()}) { | 238 E lastWhere(bool test(E value), {E orElse()}); |
| 307 // TODO(floitsch): check that arguments are of correct type? | |
| 308 E result = null; | |
| 309 bool foundMatching = false; | |
| 310 for (E element in this) { | |
| 311 if (test(element)) { | |
| 312 result = element; | |
| 313 foundMatching = true; | |
| 314 } | |
| 315 } | |
| 316 if (foundMatching) return result; | |
| 317 if (orElse != null) return orElse(); | |
| 318 throw new StateError("No matching element"); | |
| 319 } | |
| 320 | 239 |
| 321 /** | 240 /** |
| 322 * Returns the single element that satisfies [f]. If no or more than one | 241 * Returns the single element that satisfies [f]. If no or more than one |
| 323 * element match then a [StateError] is thrown. | 242 * element match then a [StateError] is thrown. |
| 324 */ | 243 */ |
| 325 E singleWhere(bool test(E value)) { | 244 E singleWhere(bool test(E value)); |
| 326 // TODO(floitsch): check that argument is of correct type? | |
| 327 E result = null; | |
| 328 bool foundMatching = false; | |
| 329 for (E element in this) { | |
| 330 if (test(element)) { | |
| 331 if (foundMatching) { | |
| 332 throw new StateError("More than one matching element"); | |
| 333 } | |
| 334 result = element; | |
| 335 foundMatching = true; | |
| 336 } | |
| 337 } | |
| 338 if (foundMatching) return result; | |
| 339 throw new StateError("No matching element"); | |
| 340 } | |
| 341 | 245 |
| 342 /** | 246 /** |
| 343 * Returns the [index]th element. | 247 * Returns the [index]th element. |
| 344 * | 248 * |
| 345 * If [this] [Iterable] has fewer than [index] elements throws a | 249 * If [this] [Iterable] has fewer than [index] elements throws a |
| 346 * [RangeError]. | 250 * [RangeError]. |
| 347 * | 251 * |
| 348 * Note: if [this] does not have a deterministic iteration order then the | 252 * Note: if [this] does not have a deterministic iteration order then the |
| 349 * function may simply return any element without any iteration if there are | 253 * function may simply return any element without any iteration if there are |
| 350 * at least [index] elements in [this]. | 254 * at least [index] elements in [this]. |
| 351 */ | 255 */ |
| 352 E elementAt(int index) { | 256 E elementAt(int index); |
| 353 if (index is! int || index < 0) throw new RangeError.value(index); | |
| 354 int remaining = index; | |
| 355 for (E element in this) { | |
| 356 if (remaining == 0) return element; | |
| 357 remaining--; | |
| 358 } | |
| 359 throw new RangeError.value(index); | |
| 360 } | |
| 361 } | 257 } |
| 362 | 258 |
| 363 | 259 |
| 364 typedef E _Generator<E>(int index); | 260 typedef E _Generator<E>(int index); |
| 365 | 261 |
| 366 class _GeneratorIterable<E> extends Iterable<E> { | 262 class _GeneratorIterable<E> extends IterableBase<E> { |
| 367 final int _count; | 263 final int _count; |
| 368 final _Generator<E> _generator; | 264 final _Generator<E> _generator; |
| 369 _GeneratorIterable(this._count, this._generator); | 265 _GeneratorIterable(this._count, this._generator); |
| 370 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); | 266 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); |
| 371 } | 267 } |
| 372 | 268 |
| 373 class _GeneratorIterator<E> implements Iterator<E> { | 269 class _GeneratorIterator<E> implements Iterator<E> { |
| 374 final int _count; | 270 final int _count; |
| 375 final _Generator<E> _generator; | 271 final _Generator<E> _generator; |
| 376 int _index = 0; | 272 int _index = 0; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 388 return false; | 284 return false; |
| 389 } | 285 } |
| 390 } | 286 } |
| 391 | 287 |
| 392 E get current => _current; | 288 E get current => _current; |
| 393 } | 289 } |
| 394 | 290 |
| 395 /** | 291 /** |
| 396 * An [Iterator] that allows moving backwards as well as forwards. | 292 * An [Iterator] that allows moving backwards as well as forwards. |
| 397 */ | 293 */ |
| 398 abstract class BidirectionalIterator<T> extends Iterator<T> { | 294 abstract class BidirectionalIterator<E> implements Iterator<E> { |
| 399 /** | 295 /** |
| 400 * Move back to the previous element. | 296 * Move back to the previous element. |
| 401 * | 297 * |
| 402 * Returns true and updates [current] if successful. Returns false | 298 * Returns true and updates [current] if successful. Returns false |
| 403 * and sets [current] to null if there is no previous element. | 299 * and sets [current] to null if there is no previous element. |
| 404 */ | 300 */ |
| 405 bool movePrevious(); | 301 bool movePrevious(); |
| 406 } | 302 } |
| OLD | NEW |