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 * |
11 * This interface is used by the for-in construct to iterate over an | 11 * This interface is used by the for-in construct to iterate over an |
12 * [Iterable] object. | 12 * [Iterable] object. |
13 * The for-in construct takes an [Iterable] object at the right-hand | 13 * The for-in construct takes an [Iterable] object at the right-hand |
14 * side, and calls its [iterator] method to get an [Iterator] on it. | 14 * side, and calls its [iterator] method to get an [Iterator] on it. |
15 * | 15 * |
16 * A user-defined class that implements the [Iterable] interface can | 16 * A user-defined class that implements the [Iterable] interface can |
17 * be used as the right-hand side of a for-in construct. | 17 * be used as the right-hand side of a for-in construct. |
18 */ | 18 */ |
19 abstract class Iterable<E> { | 19 abstract class Iterable<E> { |
| 20 const Iterable(); |
| 21 |
20 /** | 22 /** |
21 * Returns an [Iterator] that iterates over this [Iterable] object. | 23 * Returns an [Iterator] that iterates over this [Iterable] object. |
22 */ | 24 */ |
23 Iterator<E> iterator(); | 25 Iterator<E> get iterator; |
24 } | 26 |
| 27 /** |
| 28 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced |
| 29 * by the result of [:f(e):]. |
| 30 * |
| 31 * This method returns a view of the mapped elements. As long as the |
| 32 * returned [Iterable] is not iterated over, the supplied function [f] will |
| 33 * not be invoked. The transformed elements will not be cached. Iterating |
| 34 * multiple times over the the returned [Iterable] will invoke the supplied |
| 35 * function [f] multiple times on the same element. |
| 36 */ |
| 37 Iterable mappedBy(f(E element)) => new MappedIterable<E, dynamic>(this, f); |
| 38 |
| 39 /** |
| 40 * Returns a lazy [Iterable] with all elements that satisfy the |
| 41 * predicate [f]. |
| 42 * |
| 43 * This method returns a view of the mapped elements. As long as the |
| 44 * returned [Iterable] is not iterated over, the supplied function [f] will |
| 45 * not be invoked. Iterating will not cache results, and thus iterating |
| 46 * multiple times over the the returned [Iterable] will invoke the supplied |
| 47 * function [f] multiple times on the same element. |
| 48 */ |
| 49 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
| 50 |
| 51 /** |
| 52 * Check whether the collection contains an element equal to [element]. |
| 53 */ |
| 54 bool contains(E element) { |
| 55 for (E e in this) { |
| 56 if (e == element) return true; |
| 57 } |
| 58 return false; |
| 59 } |
| 60 |
| 61 /** |
| 62 * Applies the function [f] to each element of this collection. |
| 63 */ |
| 64 void forEach(void f(E element)) { |
| 65 for (E element in this) f(element); |
| 66 } |
| 67 |
| 68 /** |
| 69 * Reduce a collection to a single value by iteratively combining each element |
| 70 * of the collection with an existing value using the provided function. |
| 71 * Use [initialValue] as the initial value, and the function [combine] to |
| 72 * create a new value from the previous one and an element. |
| 73 * |
| 74 * Example of calculating the sum of a collection: |
| 75 * |
| 76 * collection.reduce(0, (prev, element) => prev + element); |
| 77 */ |
| 78 dynamic reduce(var initialValue, |
| 79 dynamic combine(var previousValue, E element)) { |
| 80 var value = initialValue; |
| 81 for (E element in this) value = combine(value, element); |
| 82 return value; |
| 83 } |
| 84 |
| 85 /** |
| 86 * Returns true if every elements of this collection satisify the |
| 87 * predicate [f]. Returns false otherwise. |
| 88 */ |
| 89 bool every(bool f(E element)) { |
| 90 for (E element in this) { |
| 91 if (!f(element)) return false; |
| 92 } |
| 93 return true; |
| 94 } |
| 95 |
| 96 /** |
| 97 * Convert each element to a [String] and concatenate the strings. |
| 98 * |
| 99 * Converts each element to a [String] by calling [Object.toString] on it. |
| 100 * Then concatenates the strings, optionally separated by the [separator] |
| 101 * string. |
| 102 */ |
| 103 String join([String separator]) { |
| 104 Iterator<E> iterator = this.iterator; |
| 105 if (!iterator.moveNext()) return ""; |
| 106 StringBuffer buffer = new StringBuffer(); |
| 107 if (separator == null || separator == "") { |
| 108 do { |
| 109 buffer.add("${iterator.current}"); |
| 110 } while (iterator.moveNext()); |
| 111 } else { |
| 112 buffer.add("${iterator.current}"); |
| 113 while (iterator.moveNext()) { |
| 114 buffer.add(separator); |
| 115 buffer.add("${iterator.current}"); |
| 116 } |
| 117 } |
| 118 return buffer.toString(); |
| 119 } |
| 120 |
| 121 /** |
| 122 * Returns true if one element of this collection satisfies the |
| 123 * predicate [f]. Returns false otherwise. |
| 124 */ |
| 125 bool any(bool f(E element)) { |
| 126 for (E element in this) { |
| 127 if (f(element)) return true; |
| 128 } |
| 129 return false; |
| 130 } |
| 131 |
| 132 List<E> toList() => new List<E>.from(this); |
| 133 Set<E> toSet() => new Set<E>.from(this); |
| 134 |
| 135 /** |
| 136 * Returns the number of elements in [this]. |
| 137 * |
| 138 * Counting all elements may be involve running through all elements and can |
| 139 * therefore be slow. |
| 140 */ |
| 141 int get length { |
| 142 int count = 0; |
| 143 Iterator it = iterator; |
| 144 while (it.moveNext()) { |
| 145 count++; |
| 146 } |
| 147 return count; |
| 148 } |
| 149 |
| 150 /** |
| 151 * Find the least element in the iterable. |
| 152 * |
| 153 * Returns null if the iterable is empty. |
| 154 * Otherwise returns an element [:x:] of this [Iterable] so that |
| 155 * [:x:] is not greater than [:y:] (that is, [:compare(x, y) <= 0:]) for all |
| 156 * other elements [:y:] in the iterable. |
| 157 * |
| 158 * The [compare] function must be a proper [Comparator<T>]. If a function is |
| 159 * not provided, [compare] defaults to [Comparable.compare]. |
| 160 */ |
| 161 E min([int compare(E a, E b)]) { |
| 162 if (compare == null) compare = Comparable.compare; |
| 163 Iterator it = iterator; |
| 164 if (!it.moveNext()) return null; |
| 165 E min = it.current; |
| 166 while (it.moveNext()) { |
| 167 E current = it.current; |
| 168 if (compare(min, current) > 0) min = current; |
| 169 } |
| 170 return min; |
| 171 } |
| 172 |
| 173 /** |
| 174 * Find the largest element in the iterable. |
| 175 * |
| 176 * Returns null if the iterable is empty. |
| 177 * Otherwise returns an element [:x:] of this [Iterable] so that |
| 178 * [:x:] is not smaller than [:y:] (that is, [:compare(x, y) >= 0:]) for all |
| 179 * other elements [:y:] in the iterable. |
| 180 * |
| 181 * The [compare] function must be a proper [Comparator<T>]. If a function is |
| 182 * not provided, [compare] defaults to [Comparable.compare]. |
| 183 */ |
| 184 E max([int compare(E a, E b)]) { |
| 185 if (compare == null) compare = Comparable.compare; |
| 186 Iterator it = iterator; |
| 187 if (!it.moveNext()) return null; |
| 188 E max = it.current; |
| 189 while (it.moveNext()) { |
| 190 E current = it.current; |
| 191 if (compare(max, current) < 0) max = current; |
| 192 } |
| 193 return max; |
| 194 } |
| 195 |
| 196 /** |
| 197 * Returns true if there is no element in this collection. |
| 198 */ |
| 199 bool get isEmpty => !iterator.moveNext(); |
| 200 |
| 201 /** |
| 202 * Returns an [Iterable] with at most [n] elements. |
| 203 * |
| 204 * The returned [Iterable] may contain fewer than [n] elements, if [this] |
| 205 * contains fewer than [n] elements. |
| 206 */ |
| 207 Iterable<E> take(int n) { |
| 208 return new TakeIterable<E>(this, n); |
| 209 } |
| 210 |
| 211 /** |
| 212 * Returns an [Iterable] that stops once [test] is not satisfied anymore. |
| 213 * |
| 214 * The filtering happens lazily. Every new [Iterator] of the returned |
| 215 * [Iterable] will start iterating over the elements of [this]. |
| 216 * When the iterator encounters an element [:e:] that does not satisfy [test], |
| 217 * it discards [:e:] and moves into the finished state. That is, it will not |
| 218 * ask or provide any more elements. |
| 219 */ |
| 220 Iterable<E> takeWhile(bool test(E value)) { |
| 221 return new TakeWhileIterable<E>(this, test); |
| 222 } |
| 223 |
| 224 /** |
| 225 * Returns an [Iterable] that skips the first [n] elements. |
| 226 * |
| 227 * If [this] has fewer than [n] elements, then the resulting [Iterable] will |
| 228 * be empty. |
| 229 */ |
| 230 Iterable<E> skip(int n) { |
| 231 return new SkipIterable<E>(this, n); |
| 232 } |
| 233 |
| 234 /** |
| 235 * Returns an [Iterable] that skips elements while [test] is satisfied. |
| 236 * |
| 237 * The filtering happens lazily. Every new [Iterator] of the returned |
| 238 * [Iterable] will iterate over all elements of [this]. |
| 239 * As long as the iterator's elements do not satisfy [test] they are |
| 240 * discarded. Once an element satisfies the [test] the iterator stops testing |
| 241 * and uses every element unconditionally. |
| 242 */ |
| 243 Iterable<E> skipWhile(bool test(E value)) { |
| 244 return new SkipWhileIterable<E>(this, test); |
| 245 } |
| 246 |
| 247 /** |
| 248 * Returns the first element. |
| 249 * |
| 250 * If [this] is empty throws a [StateError]. Otherwise this method is |
| 251 * equivalent to [:this.elementAt(0):] |
| 252 */ |
| 253 E get first { |
| 254 Iterator it = iterator; |
| 255 if (!it.moveNext()) { |
| 256 throw new StateError("No elements"); |
| 257 } |
| 258 return it.current; |
| 259 } |
| 260 |
| 261 /** |
| 262 * Returns the last element. |
| 263 * |
| 264 * If [this] is empty throws a [StateError]. |
| 265 */ |
| 266 E get last { |
| 267 Iterator it = iterator; |
| 268 if (!it.moveNext()) { |
| 269 throw new StateError("No elements"); |
| 270 } |
| 271 E result; |
| 272 do { |
| 273 result = it.current; |
| 274 } while(it.moveNext()); |
| 275 return result; |
| 276 } |
| 277 |
| 278 /** |
| 279 * Returns the single element in [this]. |
| 280 * |
| 281 * If [this] is empty or has more than one element throws a [StateError]. |
| 282 */ |
| 283 E get single { |
| 284 Iterator it = iterator; |
| 285 if (!it.moveNext()) throw new StateError("No elements"); |
| 286 E result = it.current; |
| 287 if (it.moveNext()) throw new StateError("More than one element"); |
| 288 return result; |
| 289 } |
| 290 |
| 291 /** |
| 292 * Returns the first element that satisfies the given predicate [f]. |
| 293 * |
| 294 * If none matches, the result of invoking the [orElse] function is |
| 295 * returned. By default, when [orElse] is `null`, a [StateError] is |
| 296 * thrown. |
| 297 */ |
| 298 E firstMatching(bool test(E value), { E orElse() }) { |
| 299 // TODO(floitsch): check that arguments are of correct type? |
| 300 for (E element in this) { |
| 301 if (test(element)) return element; |
| 302 } |
| 303 if (orElse != null) return orElse(); |
| 304 throw new StateError("No matching element"); |
| 305 } |
| 306 |
| 307 /** |
| 308 * Returns the last element that satisfies the given predicate [f]. |
| 309 * |
| 310 * If none matches, the result of invoking the [orElse] function is |
| 311 * returned. By default, when [orElse] is [:null:], a [StateError] is |
| 312 * thrown. |
| 313 */ |
| 314 E lastMatching(bool test(E value), {E orElse()}) { |
| 315 // TODO(floitsch): check that arguments are of correct type? |
| 316 E result = null; |
| 317 bool foundMatching = false; |
| 318 for (E element in this) { |
| 319 if (test(element)) { |
| 320 result = element; |
| 321 foundMatching = true; |
| 322 } |
| 323 } |
| 324 if (foundMatching) return result; |
| 325 if (orElse != null) return orElse(); |
| 326 throw new StateError("No matching element"); |
| 327 } |
| 328 |
| 329 /** |
| 330 * Returns the single element that satisfies [f]. If no or more than one |
| 331 * element match then a [StateError] is thrown. |
| 332 */ |
| 333 E singleMatching(bool test(E value)) { |
| 334 // TODO(floitsch): check that argument is of correct type? |
| 335 E result = null; |
| 336 bool foundMatching = false; |
| 337 for (E element in this) { |
| 338 if (test(element)) { |
| 339 if (foundMatching) { |
| 340 throw new StateError("More than one matching element"); |
| 341 } |
| 342 result = element; |
| 343 foundMatching = true; |
| 344 } |
| 345 } |
| 346 if (foundMatching) return result; |
| 347 throw new StateError("No matching element"); |
| 348 } |
| 349 |
| 350 /** |
| 351 * Returns the [index]th element. |
| 352 * |
| 353 * If [this] [Iterable] has fewer than [index] elements throws a |
| 354 * [RangeError]. |
| 355 * |
| 356 * Note: if [this] does not have a deterministic iteration order then the |
| 357 * function may simply return any element without any iteration if there are |
| 358 * at least [index] elements in [this]. |
| 359 */ |
| 360 E elementAt(int index) { |
| 361 if (index is! int || index < 0) throw new RangeError.value(index); |
| 362 int remaining = index; |
| 363 for (E element in this) { |
| 364 if (remaining == 0) return element; |
| 365 remaining--; |
| 366 } |
| 367 throw new RangeError.value(index); |
| 368 } |
| 369 } |
| 370 |
| 371 typedef T _Transformation<S, T>(S value); |
| 372 |
| 373 class MappedIterable<S, T> extends Iterable<T> { |
| 374 final Iterable<S> _iterable; |
| 375 final _Transformation _f; |
| 376 |
| 377 MappedIterable(this._iterable, T this._f(S element)); |
| 378 |
| 379 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); |
| 380 |
| 381 // Length related functions are independent of the mapping. |
| 382 int get length => _iterable.length; |
| 383 bool get isEmpty => _iterable.isEmpty; |
| 384 } |
| 385 |
| 386 class MappedIterator<S, T> extends Iterator<T> { |
| 387 T _current; |
| 388 final Iterator<S> _iterator; |
| 389 final _Transformation _f; |
| 390 |
| 391 MappedIterator(this._iterator, T this._f(S element)); |
| 392 |
| 393 bool moveNext() { |
| 394 if (_iterator.moveNext()) { |
| 395 _current = _f(_iterator.current); |
| 396 return true; |
| 397 } else { |
| 398 _current = null; |
| 399 return false; |
| 400 } |
| 401 } |
| 402 |
| 403 T get current => _current; |
| 404 } |
| 405 |
| 406 typedef bool _ElementPredicate<E>(E element); |
| 407 |
| 408 class WhereIterable<E> extends Iterable<E> { |
| 409 final Iterable<E> _iterable; |
| 410 final _ElementPredicate _f; |
| 411 |
| 412 WhereIterable(this._iterable, bool this._f(E element)); |
| 413 |
| 414 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); |
| 415 } |
| 416 |
| 417 class WhereIterator<E> extends Iterator<E> { |
| 418 final Iterator<E> _iterator; |
| 419 final _ElementPredicate _f; |
| 420 |
| 421 WhereIterator(this._iterator, bool this._f(E element)); |
| 422 |
| 423 bool moveNext() { |
| 424 while (_iterator.moveNext()) { |
| 425 if (_f(_iterator.current)) { |
| 426 return true; |
| 427 } |
| 428 } |
| 429 return false; |
| 430 } |
| 431 |
| 432 E get current => _iterator.current; |
| 433 } |
| 434 |
| 435 class TakeIterable<E> extends Iterable<E> { |
| 436 final Iterable<E> _iterable; |
| 437 final int _takeCount; |
| 438 |
| 439 TakeIterable(this._iterable, this._takeCount) { |
| 440 if (_takeCount is! int || _takeCount < 0) { |
| 441 throw new ArgumentError(_takeCount); |
| 442 } |
| 443 } |
| 444 |
| 445 Iterator<E> get iterator { |
| 446 return new TakeIterator<E>(_iterable.iterator, _takeCount); |
| 447 } |
| 448 } |
| 449 |
| 450 class TakeIterator<E> extends Iterator<E> { |
| 451 final Iterator<E> _iterator; |
| 452 int _remaining; |
| 453 |
| 454 TakeIterator(this._iterator, this._remaining) { |
| 455 assert(_remaining is int && _remaining >= 0); |
| 456 } |
| 457 |
| 458 bool moveNext() { |
| 459 _remaining--; |
| 460 if (_remaining >= 0) { |
| 461 return _iterator.moveNext(); |
| 462 } |
| 463 _remaining = -1; |
| 464 return false; |
| 465 } |
| 466 |
| 467 E get current { |
| 468 if (_remaining < 0) return null; |
| 469 return _iterator.current; |
| 470 } |
| 471 } |
| 472 |
| 473 class TakeWhileIterable<E> extends Iterable<E> { |
| 474 final Iterable<E> _iterable; |
| 475 final _ElementPredicate _f; |
| 476 |
| 477 TakeWhileIterable(this._iterable, bool this._f(E element)); |
| 478 |
| 479 Iterator<E> get iterator { |
| 480 return new TakeWhileIterator<E>(_iterable.iterator, _f); |
| 481 } |
| 482 } |
| 483 |
| 484 class TakeWhileIterator<E> extends Iterator<E> { |
| 485 final Iterator<E> _iterator; |
| 486 final _ElementPredicate _f; |
| 487 bool _isFinished = false; |
| 488 |
| 489 TakeWhileIterator(this._iterator, bool this._f(E element)); |
| 490 |
| 491 bool moveNext() { |
| 492 if (_isFinished) return false; |
| 493 if (!_iterator.moveNext() || !_f(_iterator.current)) { |
| 494 _isFinished = true; |
| 495 return false; |
| 496 } |
| 497 return true; |
| 498 } |
| 499 |
| 500 E get current { |
| 501 if (_isFinished) return null; |
| 502 return _iterator.current; |
| 503 } |
| 504 } |
| 505 |
| 506 class SkipIterable<E> extends Iterable<E> { |
| 507 final Iterable<E> _iterable; |
| 508 final int _skipCount; |
| 509 |
| 510 SkipIterable(this._iterable, this._skipCount) { |
| 511 if (_skipCount is! int || _skipCount < 0) { |
| 512 throw new ArgumentError(_skipCount); |
| 513 } |
| 514 } |
| 515 |
| 516 Iterable<E> skip(int n) { |
| 517 if (n is! int || n < 0) { |
| 518 throw new ArgumentError(n); |
| 519 } |
| 520 return new SkipIterable<E>(_iterable, _skipCount + n); |
| 521 } |
| 522 |
| 523 Iterator<E> get iterator { |
| 524 return new SkipIterator<E>(_iterable.iterator, _skipCount); |
| 525 } |
| 526 } |
| 527 |
| 528 class SkipIterator<E> extends Iterator<E> { |
| 529 final Iterator<E> _iterator; |
| 530 int _skipCount; |
| 531 |
| 532 SkipIterator(this._iterator, this._skipCount) { |
| 533 assert(_skipCount is int && _skipCount >= 0); |
| 534 } |
| 535 |
| 536 bool moveNext() { |
| 537 for (int i = 0; i < _skipCount; i++) _iterator.moveNext(); |
| 538 _skipCount = 0; |
| 539 return _iterator.moveNext(); |
| 540 } |
| 541 |
| 542 E get current => _iterator.current; |
| 543 } |
| 544 |
| 545 class SkipWhileIterable<E> extends Iterable<E> { |
| 546 final Iterable<E> _iterable; |
| 547 final _ElementPredicate _f; |
| 548 |
| 549 SkipWhileIterable(this._iterable, bool this._f(E element)); |
| 550 |
| 551 Iterator<E> get iterator { |
| 552 return new SkipWhileIterator<E>(_iterable.iterator, _f); |
| 553 } |
| 554 } |
| 555 |
| 556 class SkipWhileIterator<E> extends Iterator<E> { |
| 557 final Iterator<E> _iterator; |
| 558 final _ElementPredicate _f; |
| 559 bool _hasSkipped = false; |
| 560 |
| 561 SkipWhileIterator(this._iterator, bool this._f(E element)); |
| 562 |
| 563 bool moveNext() { |
| 564 if (!_hasSkipped) { |
| 565 _hasSkipped = true; |
| 566 while (_iterator.moveNext()) { |
| 567 if (!_f(_iterator.current)) return true; |
| 568 } |
| 569 } |
| 570 return _iterator.moveNext(); |
| 571 } |
| 572 |
| 573 E get current => _iterator.current; |
| 574 } |
OLD | NEW |