| 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 * A collection of values, or "elements", that can be accessed sequentially. | 8 * A collection of values, or "elements", that can be accessed sequentially. |
| 9 * | 9 * |
| 10 * The elements of the iterable are accessed by getting an [Iterator] | 10 * The elements of the iterable are accessed by getting an [Iterator] |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 * This method returns a view of the mapped elements. As long as the | 138 * This method returns a view of the mapped elements. As long as the |
| 139 * returned [Iterable] is not iterated over, the supplied function [f] will | 139 * returned [Iterable] is not iterated over, the supplied function [f] will |
| 140 * not be invoked. The transformed elements will not be cached. Iterating | 140 * not be invoked. The transformed elements will not be cached. Iterating |
| 141 * multiple times over the the returned [Iterable] will invoke the supplied | 141 * multiple times over the the returned [Iterable] will invoke the supplied |
| 142 * function [f] multiple times on the same element. | 142 * function [f] multiple times on the same element. |
| 143 * | 143 * |
| 144 * Methods on the returned iterable are allowed to omit calling `f` | 144 * Methods on the returned iterable are allowed to omit calling `f` |
| 145 * on any element where the result isn't needed. | 145 * on any element where the result isn't needed. |
| 146 * For example, [elementAt] may call `f` only once. | 146 * For example, [elementAt] may call `f` only once. |
| 147 */ | 147 */ |
| 148 Iterable map(f(E element)); | 148 Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); |
| 149 | 149 |
| 150 /** | 150 /** |
| 151 * Returns a new lazy [Iterable] with all elements that satisfy the | 151 * Returns a new lazy [Iterable] with all elements that satisfy the |
| 152 * predicate [test]. | 152 * predicate [test]. |
| 153 * | 153 * |
| 154 * The matching elements have the same order in the returned iterable | 154 * The matching elements have the same order in the returned iterable |
| 155 * as they have in [iterator]. | 155 * as they have in [iterator]. |
| 156 * | 156 * |
| 157 * This method returns a view of the mapped elements. As long as the | 157 * This method returns a view of the mapped elements. As long as the |
| 158 * returned [Iterable] is not iterated over, the supplied function [test] will | 158 * returned [Iterable] is not iterated over, the supplied function [test] will |
| 159 * not be invoked. Iterating will not cache results, and thus iterating | 159 * not be invoked. Iterating will not cache results, and thus iterating |
| 160 * multiple times over the returned [Iterable] will invoke the supplied | 160 * multiple times over the returned [Iterable] will invoke the supplied |
| 161 * function [test] multiple times on the same element. | 161 * function [test] multiple times on the same element. |
| 162 */ | 162 */ |
| 163 Iterable<E> where(bool test(E element)); | 163 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
| 164 | 164 |
| 165 /** | 165 /** |
| 166 * Expands each element of this [Iterable]into zero or more elements. | 166 * Expands each element of this [Iterable]into zero or more elements. |
| 167 * | 167 * |
| 168 * The resulting Iterable runs through the elements returned | 168 * The resulting Iterable runs through the elements returned |
| 169 * by [f] for each element of this, in iteration order. | 169 * by [f] for each element of this, in iteration order. |
| 170 * | 170 * |
| 171 * The returned [Iterable] is lazy, and calls [f] for each element | 171 * The returned [Iterable] is lazy, and calls [f] for each element |
| 172 * of this every time it's iterated. | 172 * of this every time it's iterated. |
| 173 */ | 173 */ |
| 174 Iterable expand(Iterable f(E element)); | 174 Iterable expand(Iterable f(E element)) => |
| 175 new ExpandIterable<E, dynamic>(this, f); |
| 175 | 176 |
| 176 /** | 177 /** |
| 177 * Returns true if the collection contains an element equal to [element]. | 178 * Returns true if the collection contains an element equal to [element]. |
| 178 * | 179 * |
| 179 * This operation will check each element in order for being equal to | 180 * This operation will check each element in order for being equal to |
| 180 * [element], unless it has a more efficient way to find an element | 181 * [element], unless it has a more efficient way to find an element |
| 181 * equal to [element]. | 182 * equal to [element]. |
| 182 * | 183 * |
| 183 * The equality used to determine whether [element] is equal to an element of | 184 * The equality used to determine whether [element] is equal to an element of |
| 184 * the iterable defaults to the [Object.operator==] of the element. | 185 * the iterable defaults to the [Object.operator==] of the element. |
| 185 * | 186 * |
| 186 * Some types of iterable may have a different equality used for its elements. | 187 * Some types of iterable may have a different equality used for its elements. |
| 187 * For example, a [Set] may have a custom equality | 188 * For example, a [Set] may have a custom equality |
| 188 * (see [Set.identical]) that its `contains` uses. | 189 * (see [Set.identical]) that its `contains` uses. |
| 189 * Likewise the `Iterable` returned by a [Map.keys] call | 190 * Likewise the `Iterable` returned by a [Map.keys] call |
| 190 * should use the same equality that the `Map` uses for keys. | 191 * should use the same equality that the `Map` uses for keys. |
| 191 */ | 192 */ |
| 192 bool contains(Object element); | 193 bool contains(Object element) { |
| 194 for (E e in this) { |
| 195 if (e == element) return true; |
| 196 } |
| 197 return false; |
| 198 } |
| 199 |
| 193 | 200 |
| 194 /** | 201 /** |
| 195 * Applies the function [f] to each element of this collection in iteration | 202 * Applies the function [f] to each element of this collection in iteration |
| 196 * order. | 203 * order. |
| 197 */ | 204 */ |
| 198 void forEach(void f(E element)); | 205 void forEach(void f(E element)) { |
| 206 for (E element in this) f(element); |
| 207 } |
| 199 | 208 |
| 200 /** | 209 /** |
| 201 * Reduces a collection to a single value by iteratively combining elements | 210 * Reduces a collection to a single value by iteratively combining elements |
| 202 * of the collection using the provided function. | 211 * of the collection using the provided function. |
| 203 * | 212 * |
| 204 * The iterable must have at least one element. | 213 * The iterable must have at least one element. |
| 205 * If it has only one element, that element is returned. | 214 * If it has only one element, that element is returned. |
| 206 * | 215 * |
| 207 * Otherwise this method starts with the first element from the iterator, | 216 * Otherwise this method starts with the first element from the iterator, |
| 208 * and then combines it with the remaining elements in iteration order, | 217 * and then combines it with the remaining elements in iteration order, |
| 209 * as if by: | 218 * as if by: |
| 210 * | 219 * |
| 211 * E value = iterable.first; | 220 * E value = iterable.first; |
| 212 * iterable.skip(1).forEach((element) { | 221 * iterable.skip(1).forEach((element) { |
| 213 * value = combine(value, element); | 222 * value = combine(value, element); |
| 214 * }); | 223 * }); |
| 215 * return value; | 224 * return value; |
| 216 * | 225 * |
| 217 * Example of calculating the sum of an iterable: | 226 * Example of calculating the sum of an iterable: |
| 218 * | 227 * |
| 219 * iterable.reduce((value, element) => value + element); | 228 * iterable.reduce((value, element) => value + element); |
| 220 * | 229 * |
| 221 */ | 230 */ |
| 222 E reduce(E combine(E value, E element)); | 231 E reduce(E combine(E value, E element)) { |
| 232 Iterator<E> iterator = this.iterator; |
| 233 if (!iterator.moveNext()) { |
| 234 throw IterableElementError.noElement(); |
| 235 } |
| 236 E value = iterator.current; |
| 237 while (iterator.moveNext()) { |
| 238 value = combine(value, iterator.current); |
| 239 } |
| 240 return value; |
| 241 } |
| 223 | 242 |
| 224 /** | 243 /** |
| 225 * Reduces a collection to a single value by iteratively combining each | 244 * Reduces a collection to a single value by iteratively combining each |
| 226 * element of the collection with an existing value | 245 * element of the collection with an existing value |
| 227 * | 246 * |
| 228 * Uses [initialValue] as the initial value, | 247 * Uses [initialValue] as the initial value, |
| 229 * then iterates through the elements and updates the value with | 248 * then iterates through the elements and updates the value with |
| 230 * each element using the [combine] function, as if by: | 249 * each element using the [combine] function, as if by: |
| 231 * | 250 * |
| 232 * var value = initialValue; | 251 * var value = initialValue; |
| 233 * for (E element in this) { | 252 * for (E element in this) { |
| 234 * value = combine(value, element); | 253 * value = combine(value, element); |
| 235 * } | 254 * } |
| 236 * return value; | 255 * return value; |
| 237 * | 256 * |
| 238 * Example of calculating the sum of an iterable: | 257 * Example of calculating the sum of an iterable: |
| 239 * | 258 * |
| 240 * iterable.fold(0, (prev, element) => prev + element); | 259 * iterable.fold(0, (prev, element) => prev + element); |
| 241 * | 260 * |
| 242 */ | 261 */ |
| 243 dynamic fold(var initialValue, | 262 dynamic fold(var initialValue, |
| 244 dynamic combine(var previousValue, E element)); | 263 dynamic combine(var previousValue, E element)) { |
| 264 var value = initialValue; |
| 265 for (E element in this) value = combine(value, element); |
| 266 return value; |
| 267 } |
| 245 | 268 |
| 246 /** | 269 /** |
| 247 * Checks whether every element of this iterable satisfies [test]. | 270 * Checks whether every element of this iterable satisfies [test]. |
| 248 * | 271 * |
| 249 * Checks every element in iteration order, and returns `false` if | 272 * Checks every element in iteration order, and returns `false` if |
| 250 * any of them make [test] return `false`, otherwise returns `true`. | 273 * any of them make [test] return `false`, otherwise returns `true`. |
| 251 */ | 274 */ |
| 252 bool every(bool test(E element)); | 275 bool every(bool f(E element)) { |
| 276 for (E element in this) { |
| 277 if (!f(element)) return false; |
| 278 } |
| 279 return true; |
| 280 } |
| 253 | 281 |
| 254 /** | 282 /** |
| 255 * Converts each element to a [String] and concatenates the strings. | 283 * Converts each element to a [String] and concatenates the strings. |
| 256 * | 284 * |
| 257 * Iterates through elements of this iterable, | 285 * Iterates through elements of this iterable, |
| 258 * converts each one to a [String] by calling [Object.toString], | 286 * converts each one to a [String] by calling [Object.toString], |
| 259 * and then concatenates the strings, with the | 287 * and then concatenates the strings, with the |
| 260 * [separator] string interleaved between the elements. | 288 * [separator] string interleaved between the elements. |
| 261 */ | 289 */ |
| 262 String join([String separator = ""]) { | 290 String join([String separator = ""]) { |
| 291 Iterator<E> iterator = this.iterator; |
| 292 if (!iterator.moveNext()) return ""; |
| 263 StringBuffer buffer = new StringBuffer(); | 293 StringBuffer buffer = new StringBuffer(); |
| 264 buffer.writeAll(this, separator); | 294 if (separator == null || separator == "") { |
| 295 do { |
| 296 buffer.write("${iterator.current}"); |
| 297 } while (iterator.moveNext()); |
| 298 } else { |
| 299 buffer.write("${iterator.current}"); |
| 300 while (iterator.moveNext()) { |
| 301 buffer.write(separator); |
| 302 buffer.write("${iterator.current}"); |
| 303 } |
| 304 } |
| 265 return buffer.toString(); | 305 return buffer.toString(); |
| 266 } | 306 } |
| 267 | 307 |
| 308 |
| 268 /** | 309 /** |
| 269 * Checks whether any element of this iterable satisfies [test]. | 310 * Checks whether any element of this iterable satisfies [test]. |
| 270 * | 311 * |
| 271 * Checks every element in iteration order, and returns `true` if | 312 * Checks every element in iteration order, and returns `true` if |
| 272 * any of them make [test] return `true`, otherwise returns false. | 313 * any of them make [test] return `true`, otherwise returns false. |
| 273 */ | 314 */ |
| 274 bool any(bool test(E element)); | 315 bool any(bool f(E element)) { |
| 316 for (E element in this) { |
| 317 if (f(element)) return true; |
| 318 } |
| 319 return false; |
| 320 } |
| 275 | 321 |
| 276 /** | 322 /** |
| 277 * Creates a [List] containing the elements of this [Iterable]. | 323 * Creates a [List] containing the elements of this [Iterable]. |
| 278 * | 324 * |
| 279 * The elements are in iteration order. | 325 * The elements are in iteration order. |
| 280 * The list is fixed-length if [growable] is false. | 326 * The list is fixed-length if [growable] is false. |
| 281 */ | 327 */ |
| 282 List<E> toList({ bool growable: true }); | 328 List<E> toList({ bool growable: true }) => |
| 329 new List<E>.from(this, growable: growable); |
| 283 | 330 |
| 284 /** | 331 /** |
| 285 * Creates a [Set] containing the same elements as this iterable. | 332 * Creates a [Set] containing the same elements as this iterable. |
| 286 * | 333 * |
| 287 * The set may contain fewer elements than the iterable, | 334 * The set may contain fewer elements than the iterable, |
| 288 * if the iterable contains an element more than once, | 335 * if the iterable contains an element more than once, |
| 289 * or it contains one or more elements that are equal. | 336 * or it contains one or more elements that are equal. |
| 290 * The order of the elements in the set is not guaranteed to be the same | 337 * The order of the elements in the set is not guaranteed to be the same |
| 291 * as for the iterable. | 338 * as for the iterable. |
| 292 */ | 339 */ |
| 293 Set<E> toSet(); | 340 Set<E> toSet() => new Set<E>.from(this); |
| 294 | 341 |
| 295 /** | 342 /** |
| 296 * Returns the number of elements in [this]. | 343 * Returns the number of elements in [this]. |
| 297 * | 344 * |
| 298 * Counting all elements may involve iterating through all elements and can | 345 * Counting all elements may involve iterating through all elements and can |
| 299 * therefore be slow. | 346 * therefore be slow. |
| 300 * Some iterables have a more efficient way to find the number of elements. | 347 * Some iterables have a more efficient way to find the number of elements. |
| 301 */ | 348 */ |
| 302 int get length; | 349 int get length { |
| 350 assert(this is! EfficientLength); |
| 351 int count = 0; |
| 352 Iterator it = iterator; |
| 353 while (it.moveNext()) { |
| 354 count++; |
| 355 } |
| 356 return count; |
| 357 } |
| 303 | 358 |
| 304 /** | 359 /** |
| 305 * Returns `true` if there are no elements in this collection. | 360 * Returns `true` if there are no elements in this collection. |
| 306 * | 361 * |
| 307 * May be computed by checking if `iterator.moveNext()` returns `false`. | 362 * May be computed by checking if `iterator.moveNext()` returns `false`. |
| 308 */ | 363 */ |
| 309 bool get isEmpty; | 364 bool get isEmpty => !iterator.moveNext(); |
| 310 | 365 |
| 311 /** | 366 /** |
| 312 * Returns true if there is at least one element in this collection. | 367 * Returns true if there is at least one element in this collection. |
| 313 * | 368 * |
| 314 * May be computed by checking if `iterator.moveNext()` returns `true`. | 369 * May be computed by checking if `iterator.moveNext()` returns `true`. |
| 315 */ | 370 */ |
| 316 bool get isNotEmpty; | 371 bool get isNotEmpty => !isEmpty; |
| 317 | 372 |
| 318 /** | 373 /** |
| 319 * Returns a lazy iterable of the [count] first elements of this iterable. | 374 * Returns a lazy iterable of the [count] first elements of this iterable. |
| 320 * | 375 * |
| 321 * The returned `Iterable` may contain fewer than `count` elements, if `this` | 376 * The returned `Iterable` may contain fewer than `count` elements, if `this` |
| 322 * contains fewer than `count` elements. | 377 * contains fewer than `count` elements. |
| 323 * | 378 * |
| 324 * The elements can be computed by stepping through [iterator] until [count] | 379 * The elements can be computed by stepping through [iterator] until [count] |
| 325 * elements have been seen. | 380 * elements have been seen. |
| 326 * | 381 * |
| 327 * The `count` must not be negative. | 382 * The `count` must not be negative. |
| 328 */ | 383 */ |
| 329 Iterable<E> take(int count); | 384 Iterable<E> take(int n) { |
| 385 return new TakeIterable<E>(this, n); |
| 386 } |
| 330 | 387 |
| 331 /** | 388 /** |
| 332 * Returns a lazy iterable of the leading elements satisfying [test]. | 389 * Returns a lazy iterable of the leading elements satisfying [test]. |
| 333 * | 390 * |
| 334 * The filtering happens lazily. Every new iterator of the returned | 391 * The filtering happens lazily. Every new iterator of the returned |
| 335 * iterable starts iterating over the elements of `this`. | 392 * iterable starts iterating over the elements of `this`. |
| 336 * | 393 * |
| 337 * The elements can be computed by stepping through [iterator] until an | 394 * The elements can be computed by stepping through [iterator] until an |
| 338 * element is found where `test(element)` is false. At that point, | 395 * element is found where `test(element)` is false. At that point, |
| 339 * the returned iterable stops (its `moveNext()` returns false). | 396 * the returned iterable stops (its `moveNext()` returns false). |
| 340 */ | 397 */ |
| 341 Iterable<E> takeWhile(bool test(E value)); | 398 Iterable<E> takeWhile(bool test(E value)) { |
| 399 return new TakeWhileIterable<E>(this, test); |
| 400 } |
| 342 | 401 |
| 343 /** | 402 /** |
| 344 * Returns an Iterable that provides all but the first [count] elements. | 403 * Returns an Iterable that provides all but the first [count] elements. |
| 345 * | 404 * |
| 346 * When the returned iterable is iterated, it starts iterating over `this`, | 405 * When the returned iterable is iterated, it starts iterating over `this`, |
| 347 * first skipping past the initial [count] elements. | 406 * first skipping past the initial [count] elements. |
| 348 * If `this` has fewer than `count` elements, then the resulting Iterable is | 407 * If `this` has fewer than `count` elements, then the resulting Iterable is |
| 349 * empty. | 408 * empty. |
| 350 * After that, the remaining elements are iterated in the same order as | 409 * After that, the remaining elements are iterated in the same order as |
| 351 * in this iterable. | 410 * in this iterable. |
| 352 * | 411 * |
| 353 * The `count` must not be negative. | 412 * The `count` must not be negative. |
| 354 */ | 413 */ |
| 355 Iterable<E> skip(int count); | 414 Iterable<E> skip(int n) { |
| 415 return new SkipIterable<E>(this, n); |
| 416 } |
| 356 | 417 |
| 357 /** | 418 /** |
| 358 * Returns an Iterable that skips leading elements while [test] is satisfied. | 419 * Returns an Iterable that skips leading elements while [test] is satisfied. |
| 359 * | 420 * |
| 360 * The filtering happens lazily. Every new Iterator of the returned | 421 * The filtering happens lazily. Every new Iterator of the returned |
| 361 * Iterable iterates over all elements of `this`. | 422 * Iterable iterates over all elements of `this`. |
| 362 * | 423 * |
| 363 * The returned iterable provides elements by iterating this iterable, | 424 * The returned iterable provides elements by iterating this iterable, |
| 364 * but skipping over all initial elements where `test(element)` returns | 425 * but skipping over all initial elements where `test(element)` returns |
| 365 * true. If all elements satisfy `test` the resulting iterable is empty, | 426 * true. If all elements satisfy `test` the resulting iterable is empty, |
| 366 * otherwise it iterates the remaining elements in their original order, | 427 * otherwise it iterates the remaining elements in their original order, |
| 367 * starting with the first element for which `test(element)` returns false, | 428 * starting with the first element for which `test(element)` returns false, |
| 368 */ | 429 */ |
| 369 Iterable<E> skipWhile(bool test(E value)); | 430 Iterable<E> skipWhile(bool test(E value)) { |
| 431 return new SkipWhileIterable<E>(this, test); |
| 432 } |
| 370 | 433 |
| 371 /** | 434 /** |
| 372 * Returns the first element. | 435 * Returns the first element. |
| 373 * | 436 * |
| 374 * Throws a [StateError] if `this` is empty. | 437 * Throws a [StateError] if `this` is empty. |
| 375 * Otherwise returs the first element in the iteration order, | 438 * Otherwise returs the first element in the iteration order, |
| 376 * equivalent to `(iterator..moveNext())..current`. | 439 * equivalent to `(iterator..moveNext())..current`. |
| 377 */ | 440 */ |
| 378 E get first; | 441 E get first { |
| 442 Iterator it = iterator; |
| 443 if (!it.moveNext()) { |
| 444 throw IterableElementError.noElement(); |
| 445 } |
| 446 return it.current; |
| 447 } |
| 379 | 448 |
| 380 /** | 449 /** |
| 381 * Returns the last element. | 450 * Returns the last element. |
| 382 * | 451 * |
| 383 * Throws a [StateError] if `this` is empty. | 452 * Throws a [StateError] if `this` is empty. |
| 384 * Otherwise may iterate through the elements and returns the last one | 453 * Otherwise may iterate through the elements and returns the last one |
| 385 * seen. | 454 * seen. |
| 386 * Some iterables may have more efficient ways to find the last element | 455 * Some iterables may have more efficient ways to find the last element |
| 387 * (for example a list can directly access the last element, | 456 * (for example a list can directly access the last element, |
| 388 * without iterating through the previous ones). | 457 * without iterating through the previous ones). |
| 389 */ | 458 */ |
| 390 E get last; | 459 E get last { |
| 460 Iterator it = iterator; |
| 461 if (!it.moveNext()) { |
| 462 throw IterableElementError.noElement(); |
| 463 } |
| 464 E result; |
| 465 do { |
| 466 result = it.current; |
| 467 } while(it.moveNext()); |
| 468 return result; |
| 469 } |
| 391 | 470 |
| 392 /** | 471 /** |
| 393 * Checks that this iterable has only one element, and returns that element. | 472 * Checks that this iterable has only one element, and returns that element. |
| 394 * | 473 * |
| 395 * Throws a [StateError] if `this` is empty or has more than one element. | 474 * Throws a [StateError] if `this` is empty or has more than one element. |
| 396 */ | 475 */ |
| 397 E get single; | 476 E get single { |
| 477 Iterator it = iterator; |
| 478 if (!it.moveNext()) throw IterableElementError.noElement(); |
| 479 E result = it.current; |
| 480 if (it.moveNext()) throw IterableElementError.tooMany(); |
| 481 return result; |
| 482 } |
| 398 | 483 |
| 399 /** | 484 /** |
| 400 * Returns the first element that satisfies the given predicate [test]. | 485 * Returns the first element that satisfies the given predicate [test]. |
| 401 * | 486 * |
| 402 * Iterates through elements and returns the first to satsify [test]. | 487 * Iterates through elements and returns the first to satsify [test]. |
| 403 * | 488 * |
| 404 * If no element satisfies [test], the result of invoking the [orElse] | 489 * If no element satisfies [test], the result of invoking the [orElse] |
| 405 * function is returned. | 490 * function is returned. |
| 406 * If [orElse] is omitted, it defaults to throwing a [StateError]. | 491 * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| 407 */ | 492 */ |
| 408 E firstWhere(bool test(E element), { E orElse() }); | 493 E firstWhere(bool test(E element), { E orElse() }) { |
| 494 for (E element in this) { |
| 495 if (test(element)) return element; |
| 496 } |
| 497 if (orElse != null) return orElse(); |
| 498 throw IterableElementError.noElement(); |
| 499 } |
| 409 | 500 |
| 410 /** | 501 /** |
| 411 * Returns the last element that satisfies the given predicate [test]. | 502 * Returns the last element that satisfies the given predicate [test]. |
| 412 * | 503 * |
| 413 * An iterable that can access its elements directly may check its | 504 * An iterable that can access its elements directly may check its |
| 414 * elements in any order (for example a list starts by checking the | 505 * elements in any order (for example a list starts by checking the |
| 415 * last element and then moves towards the start of the list). | 506 * last element and then moves towards the start of the list). |
| 416 * The default implementation iterates elements in iteration order, | 507 * The default implementation iterates elements in iteration order, |
| 417 * checks `test(element)` for each, | 508 * checks `test(element)` for each, |
| 418 * and finally returns that last one that matched. | 509 * and finally returns that last one that matched. |
| 419 * | 510 * |
| 420 * If no element satsfies [test], the result of invoking the [orElse] | 511 * If no element satsfies [test], the result of invoking the [orElse] |
| 421 * function is returned. | 512 * function is returned. |
| 422 * If [orElse] is omitted, it defaults to throwing a [StateError]. | 513 * If [orElse] is omitted, it defaults to throwing a [StateError]. |
| 423 */ | 514 */ |
| 424 E lastWhere(bool test(E element), {E orElse()}); | 515 E lastWhere(bool test(E element), {E orElse()}) { |
| 516 E result = null; |
| 517 bool foundMatching = false; |
| 518 for (E element in this) { |
| 519 if (test(element)) { |
| 520 result = element; |
| 521 foundMatching = true; |
| 522 } |
| 523 } |
| 524 if (foundMatching) return result; |
| 525 if (orElse != null) return orElse(); |
| 526 throw IterableElementError.noElement(); |
| 527 } |
| 425 | 528 |
| 426 /** | 529 /** |
| 427 * Returns the single element that satisfies [test]. | 530 * Returns the single element that satisfies [test]. |
| 428 * | 531 * |
| 429 * Checks all elements to see if `test(element)` returns true. | 532 * Checks all elements to see if `test(element)` returns true. |
| 430 * If exactly one element satisfies [test], that element is returned. | 533 * If exactly one element satisfies [test], that element is returned. |
| 431 * Otherwise, if there are no matching elements, or if there is more than | 534 * Otherwise, if there are no matching elements, or if there is more than |
| 432 * one matching element, a [StateError] is thrown. | 535 * one matching element, a [StateError] is thrown. |
| 433 */ | 536 */ |
| 434 E singleWhere(bool test(E element)); | 537 E singleWhere(bool test(E element)) { |
| 538 E result = null; |
| 539 bool foundMatching = false; |
| 540 for (E element in this) { |
| 541 if (test(element)) { |
| 542 if (foundMatching) { |
| 543 throw IterableElementError.tooMany(); |
| 544 } |
| 545 result = element; |
| 546 foundMatching = true; |
| 547 } |
| 548 } |
| 549 if (foundMatching) return result; |
| 550 throw IterableElementError.noElement(); |
| 551 } |
| 435 | 552 |
| 436 /** | 553 /** |
| 437 * Returns the [index]th element. | 554 * Returns the [index]th element. |
| 438 * | 555 * |
| 439 * The [index] must be non-negative and less than [length]. | 556 * The [index] must be non-negative and less than [length]. |
| 440 * Index zero represents the first element (so `iterable.elementAt(0)` is | 557 * Index zero represents the first element (so `iterable.elementAt(0)` is |
| 441 * equivalent to `iterable.first`). | 558 * equivalent to `iterable.first`). |
| 442 * | 559 * |
| 443 * May iterate through the elements in iteration order, skipping the | 560 * May iterate through the elements in iteration order, skipping the |
| 444 * first `index` elements and returning the next. | 561 * first `index` elements and returning the next. |
| 445 * Some iterable may have more efficient ways to find the element. | 562 * Some iterable may have more efficient ways to find the element. |
| 446 */ | 563 */ |
| 447 E elementAt(int index); | 564 E elementAt(int index) { |
| 565 if (index is! int) throw new ArgumentError.notNull("index"); |
| 566 RangeError.checkNotNegative(index, "index"); |
| 567 int elementIndex = 0; |
| 568 for (E element in this) { |
| 569 if (index == elementIndex) return element; |
| 570 elementIndex++; |
| 571 } |
| 572 throw new RangeError.index(index, this, "index", null, elementIndex); |
| 573 } |
| 574 |
| 575 /** |
| 576 * Returns a string representation of (some of) the elements of `this`. |
| 577 * |
| 578 * Elements are represented by their own `toString` results. |
| 579 * |
| 580 * The default representation always contains the first three elements. |
| 581 * If there are less than a hundred elements in the iterable, it also |
| 582 * contains the last two elements. |
| 583 * |
| 584 * If the resulting string isn't above 80 characters, more elements are |
| 585 * included from the start of the iterable. |
| 586 * |
| 587 * The conversion may omit calling `toString` on some elements if they |
| 588 * are known to not occur in the output, and it may stop iterating after |
| 589 * a hundred elements. |
| 590 */ |
| 591 String toString() => IterableBase.iterableToShortString(this, '(', ')'); |
| 448 } | 592 } |
| 449 | 593 |
| 450 typedef E _Generator<E>(int index); | 594 typedef E _Generator<E>(int index); |
| 451 | 595 |
| 452 class _GeneratorIterable<E> extends IterableBase<E> | 596 class _GeneratorIterable<E> extends Iterable<E> |
| 453 implements EfficientLength { | 597 implements EfficientLength { |
| 454 final int _start; | 598 final int _start; |
| 455 final int _end; | 599 final int _end; |
| 456 final _Generator<E> _generator; | 600 final _Generator<E> _generator; |
| 457 _GeneratorIterable(this._end, E generator(int n)) | 601 _GeneratorIterable(this._end, E generator(int n)) |
| 458 : _start = 0, | 602 : _start = 0, |
| 459 _generator = (generator != null) ? generator : _id; | 603 _generator = (generator != null) ? generator : _id; |
| 460 | 604 |
| 461 _GeneratorIterable.slice(this._start, this._end, this._generator); | 605 _GeneratorIterable.slice(this._start, this._end, this._generator); |
| 462 | 606 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 */ | 654 */ |
| 511 abstract class BidirectionalIterator<E> implements Iterator<E> { | 655 abstract class BidirectionalIterator<E> implements Iterator<E> { |
| 512 /** | 656 /** |
| 513 * Move back to the previous element. | 657 * Move back to the previous element. |
| 514 * | 658 * |
| 515 * Returns true and updates [current] if successful. Returns false | 659 * Returns true and updates [current] if successful. Returns false |
| 516 * and sets [current] to null if there is no previous element. | 660 * and sets [current] to null if there is no previous element. |
| 517 */ | 661 */ |
| 518 bool movePrevious(); | 662 bool movePrevious(); |
| 519 } | 663 } |
| OLD | NEW |