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 |