Index: pkg/collection/lib/wrappers.dart |
diff --git a/pkg/collection/lib/wrappers.dart b/pkg/collection/lib/wrappers.dart |
index 0fcc8c23e80a42f6e86c84ebea3988f512cfca02..cd4da3f8ac59677202cb557932339867bf801724 100644 |
--- a/pkg/collection/lib/wrappers.dart |
+++ b/pkg/collection/lib/wrappers.dart |
@@ -19,19 +19,15 @@ export "dart:collection" show UnmodifiableListView; |
part "src/unmodifiable_wrappers.dart"; |
/** |
- * Creates an [Iterable] that delegates all operations to a base iterable. |
+ * A base class for delegating iterables. |
* |
- * This class can be used hide non-`Iterable` methods of an iterable object, |
- * or it can be extended to add extra functionality on top of an existing |
- * iterable object. |
+ * Subclasses can provide a [_base] that should be delegated to. Unlike |
+ * [DelegatingIterable], this allows the base to be created on demand. |
*/ |
-class DelegatingIterable<E> implements Iterable<E> { |
- final Iterable<E> _base; |
+abstract class _DelegatingIterableBase<E> implements Iterable<E> { |
+ Iterable<E> get _base; |
- /** |
- * Create a wrapper that forwards operations to [base]. |
- */ |
- const DelegatingIterable(Iterable<E> base) : _base = base; |
+ const _DelegatingIterableBase(); |
bool any(bool test(E element)) => _base.any(test); |
@@ -93,6 +89,22 @@ class DelegatingIterable<E> implements Iterable<E> { |
String toString() => _base.toString(); |
} |
+/** |
+ * Creates an [Iterable] that delegates all operations to a base iterable. |
+ * |
+ * This class can be used hide non-`Iterable` methods of an iterable object, |
+ * or it can be extended to add extra functionality on top of an existing |
+ * iterable object. |
+ */ |
+class DelegatingIterable<E> extends _DelegatingIterableBase<E> { |
+ final Iterable<E> _base; |
+ |
+ /** |
+ * Create a wrapper that forwards operations to [base]. |
+ */ |
+ const DelegatingIterable(Iterable<E> base) : _base = base; |
+} |
+ |
/** |
* Creates a [List] that delegates all operations to a base list. |
@@ -337,3 +349,129 @@ class DelegatingMap<K, V> implements Map<K, V> { |
String toString() => _base.toString(); |
} |
+ |
+/** |
+ * Creates an unmodifiable [Set] that delegates all operations to a base map's |
+ * keys. |
+ * |
+ * This class can be used to make a `Map` look like a `Set`. Note that [lookup] |
+ * is not `O(1)` for this set. |
+ */ |
+class MapKeySet<E> extends _DelegatingIterableBase<E> |
+ with UnmodifiableSetMixin<E> { |
+ final Map<E, dynamic> _baseMap; |
+ |
+ Iterable<E> get _base => _baseMap.keys; |
+ |
+ MapKeySet(Map<E, dynamic> base) : _baseMap = base; |
+ |
+ bool contains(Object element) => _baseMap.containsKey(element); |
+ |
+ bool get isEmpty => _baseMap.isEmpty; |
+ |
+ bool get isNotEmpty => _baseMap.isNotEmpty; |
+ |
+ int get length => _baseMap.length; |
+ |
+ String toString() => toSet().toString(); |
+ |
+ bool containsAll(Iterable<Object> other) => other.every(contains); |
+ |
+ Set<E> difference(Set<E> other) => |
+ where((element) => !other.contains(element)).toSet(); |
+ |
+ Set<E> intersection(Set<Object> other) => |
+ where((element) => other.contains(element)).toSet(); |
+ |
+ E lookup(E element) => firstWhere((key) => element == key, |
+ orElse: () => null); |
+ |
+ Set<E> union(Set<E> other) => toSet()..addAll(other); |
+} |
+ |
+/** |
+ * Creates a [Set] that delegates all operations to a base map's values. |
+ * |
+ * This class can be used to make a `Map` whose keys are determinable from its |
kevmoo
2014/05/08 20:40:15
I'm a bit confused by this sentence. What's the us
nweiz
2014/05/08 21:14:56
See my comment on the issue: https://code.google.c
kevmoo
2014/05/08 23:01:53
Your comment makes the usage clear, but the docs h
nweiz
2014/05/09 02:48:50
Done.
|
+ * values look like a `Set`. |
+ */ |
+class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { |
+ final Map<K, V> _baseMap; |
+ final Function _keyForValue; |
+ |
+ Iterable<V> get _base => _baseMap.values; |
+ |
+ /** |
+ * Creates a new [MapValueSet] based on [base]. |
+ * |
+ * [keyForValue] returns the key in the map that should be associated with the |
+ * given value. The set's notion of equality is identical to the equality of |
+ * the return values of [keyForValue]. |
+ */ |
+ MapValueSet(Map<K, V> base, K keyForValue(V value)) |
+ : _baseMap = base, |
+ _keyForValue = keyForValue; |
+ |
+ bool contains(Object element) { |
+ if (element is! V) return false; |
+ return _baseMap.containsKey(_keyForValue(element)); |
+ } |
+ |
+ bool get isEmpty => _baseMap.isEmpty; |
+ |
+ bool get isNotEmpty => _baseMap.isNotEmpty; |
+ |
+ int get length => _baseMap.length; |
+ |
+ String toString() => toSet().toString(); |
+ |
+ bool add(V value) { |
+ var key = _keyForValue(value); |
+ if (_baseMap.containsKey(key)) return false; |
+ _baseMap[key] = value; |
+ return true; |
+ } |
+ |
+ void addAll(Iterable<V> elements) => elements.forEach(add); |
+ |
+ void clear() => _baseMap.clear(); |
+ |
+ bool containsAll(Iterable<Object> other) => other.every(contains); |
+ |
+ Set<V> difference(Set<V> other) => |
+ where((element) => !other.contains(element)).toSet(); |
+ |
+ Set<V> intersection(Set<Object> other) => |
+ where((element) => other.contains(element)).toSet(); |
+ |
+ V lookup(V element) => _baseMap[_keyForValue(element)]; |
+ |
+ bool remove(Object value) { |
+ if (value is! V) return false; |
+ var key = _keyForValue(value); |
+ if (!_baseMap.containsKey(key)) return false; |
+ _baseMap.remove(key); |
+ return true; |
+ } |
+ |
+ void removeAll(Iterable<Object> elements) => elements.forEach(remove); |
+ |
+ void removeWhere(bool test(V element)) { |
+ new Map.from(_baseMap).forEach((key, value) { |
+ if (test(value)) remove(key); |
+ }); |
+ } |
+ |
+ void retainAll(Iterable<Object> elements) { |
+ var retainKeys = elements.where((element) => element is V) |
+ .map((element) => _keyForValue(element)).toSet(); |
+ new Map.from(_baseMap).forEach((key, value) { |
+ if (!retainKeys.contains(key)) remove(key); |
+ }); |
+ } |
+ |
+ void retainWhere(bool test(V element)) => |
+ removeWhere((element) => !test(element)); |
+ |
+ Set<V> union(Set<V> other) => toSet()..addAll(other); |
+} |