| 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 * Reduces 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 * Reduces a collection to a single value by iteratively combining each |
| 118 * of the collection with an existing value using the provided function. | 99 * element of the collection with an existing value using the provided |
| 100 * function. |
| 101 * |
| 119 * Use [initialValue] as the initial value, and the function [combine] to | 102 * Use [initialValue] as the initial value, and the function [combine] to |
| 120 * create a new value from the previous one and an element. | 103 * create a new value from the previous one and an element. |
| 121 * | 104 * |
| 122 * Example of calculating the sum of an iterable: | 105 * Example of calculating the sum of an iterable: |
| 123 * | 106 * |
| 124 * iterable.fold(0, (prev, element) => prev + element); | 107 * iterable.fold(0, (prev, element) => prev + element); |
| 125 * | 108 * |
| 126 */ | 109 */ |
| 127 dynamic fold(var initialValue, | 110 dynamic fold(var initialValue, |
| 128 dynamic combine(var previousValue, E element)) { | 111 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 | 112 |
| 134 /** | 113 /** |
| 135 * Returns true if every elements of this collection satisify the | 114 * Returns true if every elements of this collection satisify the |
| 136 * predicate [f]. Returns false otherwise. | 115 * predicate [f]. Returns false otherwise. |
| 137 */ | 116 */ |
| 138 bool every(bool f(E element)) { | 117 bool every(bool f(E element)); |
| 139 for (E element in this) { | |
| 140 if (!f(element)) return false; | |
| 141 } | |
| 142 return true; | |
| 143 } | |
| 144 | 118 |
| 145 /** | 119 /** |
| 146 * Convert each element to a [String] and concatenate the strings. | 120 * Converts each element to a [String] and concatenates the strings. |
| 147 * | 121 * |
| 148 * Converts each element to a [String] by calling [Object.toString] on it. | 122 * Converts each element to a [String] by calling [Object.toString] on it. |
| 149 * Then concatenates the strings, optionally separated by the [separator] | 123 * Then concatenates the strings, optionally separated by the [separator] |
| 150 * string. | 124 * string. |
| 151 */ | 125 */ |
| 152 String join([String separator = ""]) { | 126 String join([String separator = ""]) { |
| 153 StringBuffer buffer = new StringBuffer(); | 127 StringBuffer buffer = new StringBuffer(); |
| 154 buffer.writeAll(this, separator); | 128 buffer.writeAll(this, separator); |
| 155 return buffer.toString(); | 129 return buffer.toString(); |
| 156 } | 130 } |
| 157 | 131 |
| 158 /** | 132 /** |
| 159 * Returns true if one element of this collection satisfies the | 133 * Returns true if one element of this collection satisfies the |
| 160 * predicate [f]. Returns false otherwise. | 134 * predicate [f]. Returns false otherwise. |
| 161 */ | 135 */ |
| 162 bool any(bool f(E element)) { | 136 bool any(bool f(E element)); |
| 163 for (E element in this) { | |
| 164 if (f(element)) return true; | |
| 165 } | |
| 166 return false; | |
| 167 } | |
| 168 | 137 |
| 169 List<E> toList({ bool growable: true }) => | 138 /** |
| 170 new List<E>.from(this, growable: growable); | 139 * Creates a [List] containing the elements of this [Iterable]. |
| 171 Set<E> toSet() => new Set<E>.from(this); | 140 * |
| 141 * The elements will be in iteration order. The list is fixed-length |
| 142 * if [growable] is false. |
| 143 */ |
| 144 List<E> toList({ bool growable: true }); |
| 145 |
| 146 /** |
| 147 * Creates a [Set] containing the elements of this [Iterable]. |
| 148 */ |
| 149 Set<E> toSet(); |
| 172 | 150 |
| 173 /** | 151 /** |
| 174 * Returns the number of elements in [this]. | 152 * Returns the number of elements in [this]. |
| 175 * | 153 * |
| 176 * Counting all elements may be involve running through all elements and can | 154 * Counting all elements may be involve running through all elements and can |
| 177 * therefore be slow. | 155 * therefore be slow. |
| 178 */ | 156 */ |
| 179 int get length { | 157 int get length; |
| 180 int count = 0; | |
| 181 Iterator it = iterator; | |
| 182 while (it.moveNext()) { | |
| 183 count++; | |
| 184 } | |
| 185 return count; | |
| 186 } | |
| 187 | 158 |
| 188 /** | 159 /** |
| 189 * Returns true if there is no element in this collection. | 160 * Returns true if there is no element in this collection. |
| 190 */ | 161 */ |
| 191 bool get isEmpty => !iterator.moveNext(); | 162 bool get isEmpty; |
| 192 | 163 |
| 193 /** | 164 /** |
| 194 * Returns an [Iterable] with at most [n] elements. | 165 * Returns an [Iterable] with at most [n] elements. |
| 195 * | 166 * |
| 196 * The returned [Iterable] may contain fewer than [n] elements, if [this] | 167 * The returned [Iterable] may contain fewer than [n] elements, if [this] |
| 197 * contains fewer than [n] elements. | 168 * contains fewer than [n] elements. |
| 198 */ | 169 */ |
| 199 Iterable<E> take(int n) { | 170 Iterable<E> take(int n); |
| 200 return new TakeIterable<E>(this, n); | |
| 201 } | |
| 202 | 171 |
| 203 /** | 172 /** |
| 204 * Returns an [Iterable] that stops once [test] is not satisfied anymore. | 173 * Returns an [Iterable] that stops once [test] is not satisfied anymore. |
| 205 * | 174 * |
| 206 * The filtering happens lazily. Every new [Iterator] of the returned | 175 * The filtering happens lazily. Every new [Iterator] of the returned |
| 207 * [Iterable] will start iterating over the elements of [this]. | 176 * [Iterable] will start iterating over the elements of [this]. |
| 208 * When the iterator encounters an element [:e:] that does not satisfy [test], | 177 * 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 | 178 * it discards [:e:] and moves into the finished state. That is, it will not |
| 210 * ask or provide any more elements. | 179 * ask or provide any more elements. |
| 211 */ | 180 */ |
| 212 Iterable<E> takeWhile(bool test(E value)) { | 181 Iterable<E> takeWhile(bool test(E value)); |
| 213 return new TakeWhileIterable<E>(this, test); | |
| 214 } | |
| 215 | 182 |
| 216 /** | 183 /** |
| 217 * Returns an [Iterable] that skips the first [n] elements. | 184 * Returns an [Iterable] that skips the first [n] elements. |
| 218 * | 185 * |
| 219 * If [this] has fewer than [n] elements, then the resulting [Iterable] will | 186 * If [this] has fewer than [n] elements, then the resulting [Iterable] will |
| 220 * be empty. | 187 * be empty. |
| 221 */ | 188 */ |
| 222 Iterable<E> skip(int n) { | 189 Iterable<E> skip(int n); |
| 223 return new SkipIterable<E>(this, n); | |
| 224 } | |
| 225 | 190 |
| 226 /** | 191 /** |
| 227 * Returns an [Iterable] that skips elements while [test] is satisfied. | 192 * Returns an [Iterable] that skips elements while [test] is satisfied. |
| 228 * | 193 * |
| 229 * The filtering happens lazily. Every new [Iterator] of the returned | 194 * The filtering happens lazily. Every new [Iterator] of the returned |
| 230 * [Iterable] will iterate over all elements of [this]. | 195 * [Iterable] will iterate over all elements of [this]. |
| 231 * As long as the iterator's elements do not satisfy [test] they are | 196 * 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 | 197 * discarded. Once an element satisfies the [test] the iterator stops testing |
| 233 * and uses every element unconditionally. | 198 * and uses every element unconditionally. |
| 234 */ | 199 */ |
| 235 Iterable<E> skipWhile(bool test(E value)) { | 200 Iterable<E> skipWhile(bool test(E value)); |
| 236 return new SkipWhileIterable<E>(this, test); | |
| 237 } | |
| 238 | 201 |
| 239 /** | 202 /** |
| 240 * Returns the first element. | 203 * Returns the first element. |
| 241 * | 204 * |
| 242 * If [this] is empty throws a [StateError]. Otherwise this method is | 205 * If [this] is empty throws a [StateError]. Otherwise this method is |
| 243 * equivalent to [:this.elementAt(0):] | 206 * equivalent to [:this.elementAt(0):] |
| 244 */ | 207 */ |
| 245 E get first { | 208 E get first; |
| 246 Iterator it = iterator; | |
| 247 if (!it.moveNext()) { | |
| 248 throw new StateError("No elements"); | |
| 249 } | |
| 250 return it.current; | |
| 251 } | |
| 252 | 209 |
| 253 /** | 210 /** |
| 254 * Returns the last element. | 211 * Returns the last element. |
| 255 * | 212 * |
| 256 * If [this] is empty throws a [StateError]. | 213 * If [this] is empty throws a [StateError]. |
| 257 */ | 214 */ |
| 258 E get last { | 215 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 | 216 |
| 270 /** | 217 /** |
| 271 * Returns the single element in [this]. | 218 * Returns the single element in [this]. |
| 272 * | 219 * |
| 273 * If [this] is empty or has more than one element throws a [StateError]. | 220 * If [this] is empty or has more than one element throws a [StateError]. |
| 274 */ | 221 */ |
| 275 E get single { | 222 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 | 223 |
| 283 /** | 224 /** |
| 284 * Returns the first element that satisfies the given predicate [f]. | 225 * Returns the first element that satisfies the given predicate [f]. |
| 285 * | 226 * |
| 286 * If none matches, the result of invoking the [orElse] function is | 227 * If none matches, the result of invoking the [orElse] function is |
| 287 * returned. By default, when [orElse] is `null`, a [StateError] is | 228 * returned. By default, when [orElse] is `null`, a [StateError] is |
| 288 * thrown. | 229 * thrown. |
| 289 */ | 230 */ |
| 290 E firstWhere(bool test(E value), { E orElse() }) { | 231 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 | 232 |
| 299 /** | 233 /** |
| 300 * Returns the last element that satisfies the given predicate [f]. | 234 * Returns the last element that satisfies the given predicate [f]. |
| 301 * | 235 * |
| 302 * If none matches, the result of invoking the [orElse] function is | 236 * If none matches, the result of invoking the [orElse] function is |
| 303 * returned. By default, when [orElse] is [:null:], a [StateError] is | 237 * returned. By default, when [orElse] is [:null:], a [StateError] is |
| 304 * thrown. | 238 * thrown. |
| 305 */ | 239 */ |
| 306 E lastWhere(bool test(E value), {E orElse()}) { | 240 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 | 241 |
| 321 /** | 242 /** |
| 322 * Returns the single element that satisfies [f]. If no or more than one | 243 * Returns the single element that satisfies [f]. If no or more than one |
| 323 * element match then a [StateError] is thrown. | 244 * element match then a [StateError] is thrown. |
| 324 */ | 245 */ |
| 325 E singleWhere(bool test(E value)) { | 246 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 | 247 |
| 342 /** | 248 /** |
| 343 * Returns the [index]th element. | 249 * Returns the [index]th element. |
| 344 * | 250 * |
| 345 * If [this] [Iterable] has fewer than [index] elements throws a | 251 * If [this] [Iterable] has fewer than [index] elements throws a |
| 346 * [RangeError]. | 252 * [RangeError]. |
| 347 * | 253 * |
| 348 * Note: if [this] does not have a deterministic iteration order then the | 254 * 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 | 255 * function may simply return any element without any iteration if there are |
| 350 * at least [index] elements in [this]. | 256 * at least [index] elements in [this]. |
| 351 */ | 257 */ |
| 352 E elementAt(int index) { | 258 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 } | 259 } |
| 362 | 260 |
| 363 | 261 |
| 364 typedef E _Generator<E>(int index); | 262 typedef E _Generator<E>(int index); |
| 365 | 263 |
| 366 class _GeneratorIterable<E> extends Iterable<E> { | 264 class _GeneratorIterable<E> extends IterableBase<E> { |
| 367 final int _count; | 265 final int _count; |
| 368 final _Generator<E> _generator; | 266 final _Generator<E> _generator; |
| 369 _GeneratorIterable(this._count, this._generator); | 267 _GeneratorIterable(this._count, this._generator); |
| 370 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); | 268 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); |
| 371 } | 269 } |
| 372 | 270 |
| 373 class _GeneratorIterator<E> implements Iterator<E> { | 271 class _GeneratorIterator<E> implements Iterator<E> { |
| 374 final int _count; | 272 final int _count; |
| 375 final _Generator<E> _generator; | 273 final _Generator<E> _generator; |
| 376 int _index = 0; | 274 int _index = 0; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 388 return false; | 286 return false; |
| 389 } | 287 } |
| 390 } | 288 } |
| 391 | 289 |
| 392 E get current => _current; | 290 E get current => _current; |
| 393 } | 291 } |
| 394 | 292 |
| 395 /** | 293 /** |
| 396 * An [Iterator] that allows moving backwards as well as forwards. | 294 * An [Iterator] that allows moving backwards as well as forwards. |
| 397 */ | 295 */ |
| 398 abstract class BidirectionalIterator<T> extends Iterator<T> { | 296 abstract class BidirectionalIterator<E> implements Iterator<E> { |
| 399 /** | 297 /** |
| 400 * Move back to the previous element. | 298 * Move back to the previous element. |
| 401 * | 299 * |
| 402 * Returns true and updates [current] if successful. Returns false | 300 * Returns true and updates [current] if successful. Returns false |
| 403 * and sets [current] to null if there is no previous element. | 301 * and sets [current] to null if there is no previous element. |
| 404 */ | 302 */ |
| 405 bool movePrevious(); | 303 bool movePrevious(); |
| 406 } | 304 } |
| OLD | NEW |