OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import "dart:collection"; | 5 import "dart:collection"; |
6 import "dart:math" as math; | 6 import "dart:math" as math; |
7 | 7 |
8 import "unmodifiable_wrappers.dart"; | 8 import "unmodifiable_wrappers.dart"; |
9 | 9 |
| 10 typedef K _KeyForValue<K, V>(V value); |
| 11 |
10 /// A base class for delegating iterables. | 12 /// A base class for delegating iterables. |
11 /// | 13 /// |
12 /// Subclasses can provide a [_base] that should be delegated to. Unlike | 14 /// Subclasses can provide a [_base] that should be delegated to. Unlike |
13 /// [DelegatingIterable], this allows the base to be created on demand. | 15 /// [DelegatingIterable], this allows the base to be created on demand. |
14 abstract class _DelegatingIterableBase<E> implements Iterable<E> { | 16 abstract class _DelegatingIterableBase<E> implements Iterable<E> { |
15 Iterable<E> get _base; | 17 Iterable<E> get _base; |
16 | 18 |
17 const _DelegatingIterableBase(); | 19 const _DelegatingIterableBase(); |
18 | 20 |
19 bool any(bool test(E element)) => _base.any(test); | 21 bool any(bool test(E element)) => _base.any(test); |
20 | 22 |
21 bool contains(Object element) => _base.contains(element); | 23 bool contains(Object element) => _base.contains(element); |
22 | 24 |
23 E elementAt(int index) => _base.elementAt(index); | 25 E elementAt(int index) => _base.elementAt(index); |
24 | 26 |
25 bool every(bool test(E element)) => _base.every(test); | 27 bool every(bool test(E element)) => _base.every(test); |
26 | 28 |
27 Iterable expand(Iterable f(E element)) => _base.expand(f); | 29 Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element)) => |
| 30 _base.expand(f); |
28 | 31 |
29 E get first => _base.first; | 32 E get first => _base.first; |
30 | 33 |
31 E firstWhere(bool test(E element), {E orElse()}) => | 34 E firstWhere(bool test(E element), {E orElse()}) => |
32 _base.firstWhere(test, orElse: orElse); | 35 _base.firstWhere(test, orElse: orElse); |
33 | 36 |
34 fold(initialValue, combine(previousValue, E element)) => | 37 /*=T*/ fold/*<T>*/( |
| 38 /*=T*/ initialValue, |
| 39 /*=T*/ combine(/*=T*/ previousValue, E element)) => |
35 _base.fold(initialValue, combine); | 40 _base.fold(initialValue, combine); |
36 | 41 |
37 void forEach(void f(E element)) => _base.forEach(f); | 42 void forEach(void f(E element)) => _base.forEach(f); |
38 | 43 |
39 bool get isEmpty => _base.isEmpty; | 44 bool get isEmpty => _base.isEmpty; |
40 | 45 |
41 bool get isNotEmpty => _base.isNotEmpty; | 46 bool get isNotEmpty => _base.isNotEmpty; |
42 | 47 |
43 Iterator<E> get iterator => _base.iterator; | 48 Iterator<E> get iterator => _base.iterator; |
44 | 49 |
45 String join([String separator = ""]) => _base.join(separator); | 50 String join([String separator = ""]) => _base.join(separator); |
46 | 51 |
47 E get last => _base.last; | 52 E get last => _base.last; |
48 | 53 |
49 E lastWhere(bool test(E element), {E orElse()}) => | 54 E lastWhere(bool test(E element), {E orElse()}) => |
50 _base.lastWhere(test, orElse: orElse); | 55 _base.lastWhere(test, orElse: orElse); |
51 | 56 |
52 int get length => _base.length; | 57 int get length => _base.length; |
53 | 58 |
54 Iterable map(f(E element)) => _base.map(f); | 59 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => _base.map(f); |
55 | 60 |
56 E reduce(E combine(E value, E element)) => _base.reduce(combine); | 61 E reduce(E combine(E value, E element)) => _base.reduce(combine); |
57 | 62 |
58 E get single => _base.single; | 63 E get single => _base.single; |
59 | 64 |
60 E singleWhere(bool test(E element)) => _base.singleWhere(test); | 65 E singleWhere(bool test(E element)) => _base.singleWhere(test); |
61 | 66 |
62 Iterable<E> skip(int n) => _base.skip(n); | 67 Iterable<E> skip(int n) => _base.skip(n); |
63 | 68 |
64 Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test); | 69 Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test); |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 /// | 389 /// |
385 /// That is, the returned set contains all the elements of this [Set] and all | 390 /// That is, the returned set contains all the elements of this [Set] and all |
386 /// the elements of [other]. | 391 /// the elements of [other]. |
387 /// | 392 /// |
388 /// Note that the returned set will use the default equality operation, which | 393 /// Note that the returned set will use the default equality operation, which |
389 /// may be different than the equality operation [this] uses. | 394 /// may be different than the equality operation [this] uses. |
390 Set<E> union(Set<E> other) => toSet()..addAll(other); | 395 Set<E> union(Set<E> other) => toSet()..addAll(other); |
391 } | 396 } |
392 | 397 |
393 /// Creates a modifiable [Set] view of the values of a [Map]. | 398 /// Creates a modifiable [Set] view of the values of a [Map]. |
394 /// | 399 /// |
395 /// The `Set` view assumes that the keys of the `Map` can be uniquely determined | 400 /// The `Set` view assumes that the keys of the `Map` can be uniquely determined |
396 /// from the values. The `keyForValue` function passed to the constructor finds | 401 /// from the values. The `keyForValue` function passed to the constructor finds |
397 /// the key for a single value. The `keyForValue` function should be consistent | 402 /// the key for a single value. The `keyForValue` function should be consistent |
398 /// with equality. If `value1 == value2` then `keyForValue(value1)` and | 403 /// with equality. If `value1 == value2` then `keyForValue(value1)` and |
399 /// `keyForValue(value2)` should be considered equal keys by the underlying map, | 404 /// `keyForValue(value2)` should be considered equal keys by the underlying map, |
400 /// and vice versa. | 405 /// and vice versa. |
401 /// | 406 /// |
402 /// Modifying the set will modify the underlying map based on the key returned | 407 /// Modifying the set will modify the underlying map based on the key returned |
403 /// by `keyForValue`. | 408 /// by `keyForValue`. |
404 /// | 409 /// |
405 /// If the `Map` contents are not compatible with the `keyForValue` function, | 410 /// If the `Map` contents are not compatible with the `keyForValue` function, |
406 /// the set will not work consistently, and may give meaningless responses or do | 411 /// the set will not work consistently, and may give meaningless responses or do |
407 /// inconsistent updates. | 412 /// inconsistent updates. |
408 /// | 413 /// |
409 /// This set can, for example, be used on a map from database record IDs to the | 414 /// This set can, for example, be used on a map from database record IDs to the |
410 /// records. It exposes the records as a set, and allows for writing both | 415 /// records. It exposes the records as a set, and allows for writing both |
411 /// `recordSet.add(databaseRecord)` and `recordMap[id]`. | 416 /// `recordSet.add(databaseRecord)` and `recordMap[id]`. |
412 /// | 417 /// |
413 /// Effectively, the map will act as a kind of index for the set. | 418 /// Effectively, the map will act as a kind of index for the set. |
414 class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { | 419 class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { |
415 final Map<K, V> _baseMap; | 420 final Map<K, V> _baseMap; |
416 final Function _keyForValue; | 421 final _KeyForValue<K, V> _keyForValue; |
417 | 422 |
418 /// Creates a new [MapValueSet] based on [base]. | 423 /// Creates a new [MapValueSet] based on [base]. |
419 /// | 424 /// |
420 /// [keyForValue] returns the key in the map that should be associated with | 425 /// [keyForValue] returns the key in the map that should be associated with |
421 /// the given value. The set's notion of equality is identical to the equality | 426 /// the given value. The set's notion of equality is identical to the equality |
422 /// of the return values of [keyForValue]. | 427 /// of the return values of [keyForValue]. |
423 MapValueSet(Map<K, V> base, K keyForValue(V value)) | 428 MapValueSet(Map<K, V> base, K keyForValue(V value)) |
424 : _baseMap = base, | 429 : _baseMap = base, |
425 _keyForValue = keyForValue; | 430 _keyForValue = keyForValue; |
426 | 431 |
427 Iterable<V> get _base => _baseMap.values; | 432 Iterable<V> get _base => _baseMap.values; |
428 | 433 |
429 bool contains(Object element) { | 434 bool contains(Object element) { |
430 if (element != null && element is! V) return false; | 435 if (element != null && element is! V) return false; |
431 return _baseMap.containsKey(_keyForValue(element)); | 436 var key = _keyForValue(element as V); |
| 437 |
| 438 return _baseMap.containsKey(key); |
432 } | 439 } |
433 | 440 |
434 bool get isEmpty => _baseMap.isEmpty; | 441 bool get isEmpty => _baseMap.isEmpty; |
435 | 442 |
436 bool get isNotEmpty => _baseMap.isNotEmpty; | 443 bool get isNotEmpty => _baseMap.isNotEmpty; |
437 | 444 |
438 int get length => _baseMap.length; | 445 int get length => _baseMap.length; |
439 | 446 |
440 String toString() => toSet().toString(); | 447 String toString() => toSet().toString(); |
441 | 448 |
(...skipping 25 matching lines...) Expand all Loading... |
467 | 474 |
468 /// Returns a new set which is the intersection between [this] and [other]. | 475 /// Returns a new set which is the intersection between [this] and [other]. |
469 /// | 476 /// |
470 /// That is, the returned set contains all the elements of this [Set] that are | 477 /// That is, the returned set contains all the elements of this [Set] that are |
471 /// also elements of [other] according to `other.contains`. | 478 /// also elements of [other] according to `other.contains`. |
472 /// | 479 /// |
473 /// Note that the returned set will use the default equality operation, which | 480 /// Note that the returned set will use the default equality operation, which |
474 /// may be different than the equality operation [this] uses. | 481 /// may be different than the equality operation [this] uses. |
475 Set<V> intersection(Set<Object> other) => where(other.contains).toSet(); | 482 Set<V> intersection(Set<Object> other) => where(other.contains).toSet(); |
476 | 483 |
477 V lookup(Object element) => _baseMap[_keyForValue(element)]; | 484 V lookup(Object element) { |
| 485 if (element != null && element is! V) return null; |
| 486 var key = _keyForValue(element as V); |
478 | 487 |
479 bool remove(Object value) { | 488 return _baseMap[key]; |
480 if (value != null && value is! V) return false; | 489 } |
481 var key = _keyForValue(value); | 490 |
| 491 bool remove(Object element) { |
| 492 if (element != null && element is! V) return false; |
| 493 var key = _keyForValue(element as V); |
| 494 |
482 if (!_baseMap.containsKey(key)) return false; | 495 if (!_baseMap.containsKey(key)) return false; |
483 _baseMap.remove(key); | 496 _baseMap.remove(key); |
484 return true; | 497 return true; |
485 } | 498 } |
486 | 499 |
487 void removeAll(Iterable<Object> elements) => elements.forEach(remove); | 500 void removeAll(Iterable<Object> elements) => elements.forEach(remove); |
488 | 501 |
489 void removeWhere(bool test(V element)) { | 502 void removeWhere(bool test(V element)) { |
490 var toRemove = []; | 503 var toRemove = []; |
491 _baseMap.forEach((key, value) { | 504 _baseMap.forEach((key, value) { |
492 if (test(value)) toRemove.add(key); | 505 if (test(value)) toRemove.add(key); |
493 }); | 506 }); |
494 toRemove.forEach(_baseMap.remove); | 507 toRemove.forEach(_baseMap.remove); |
495 } | 508 } |
496 | 509 |
497 void retainAll(Iterable<Object> elements) { | 510 void retainAll(Iterable<Object> elements) { |
498 var valuesToRetain = new Set<V>.identity(); | 511 var valuesToRetain = new Set<V>.identity(); |
499 for (var element in elements) { | 512 for (var element in elements) { |
500 if (element != null && element is! V) continue; | 513 if (element != null && element is! V) continue; |
501 var key = _keyForValue(element); | 514 var key = _keyForValue(element as V); |
| 515 |
502 if (!_baseMap.containsKey(key)) continue; | 516 if (!_baseMap.containsKey(key)) continue; |
503 valuesToRetain.add(_baseMap[key]); | 517 valuesToRetain.add(_baseMap[key]); |
504 } | 518 } |
505 | 519 |
506 var keysToRemove = []; | 520 var keysToRemove = []; |
507 _baseMap.forEach((k, v) { | 521 _baseMap.forEach((k, v) { |
508 if (!valuesToRetain.contains(v)) keysToRemove.add(k); | 522 if (!valuesToRetain.contains(v)) keysToRemove.add(k); |
509 }); | 523 }); |
510 keysToRemove.forEach(_baseMap.remove); | 524 keysToRemove.forEach(_baseMap.remove); |
511 } | 525 } |
512 | 526 |
513 void retainWhere(bool test(V element)) => | 527 void retainWhere(bool test(V element)) => |
514 removeWhere((element) => !test(element)); | 528 removeWhere((element) => !test(element)); |
515 | 529 |
516 /// Returns a new set which contains all the elements of [this] and [other]. | 530 /// Returns a new set which contains all the elements of [this] and [other]. |
517 /// | 531 /// |
518 /// That is, the returned set contains all the elements of this [Set] and all | 532 /// That is, the returned set contains all the elements of this [Set] and all |
519 /// the elements of [other]. | 533 /// the elements of [other]. |
520 /// | 534 /// |
521 /// Note that the returned set will use the default equality operation, which | 535 /// Note that the returned set will use the default equality operation, which |
522 /// may be different than the equality operation [this] uses. | 536 /// may be different than the equality operation [this] uses. |
523 Set<V> union(Set<V> other) => toSet()..addAll(other); | 537 Set<V> union(Set<V> other) => toSet()..addAll(other); |
524 } | 538 } |
OLD | NEW |