Skip to content

Commit

Permalink
Introduce IterableMapEntryExtension for use with Map.entries.
Browse files Browse the repository at this point in the history
**Example**:
```dart
final myMap = {
  'foo': 42,
  'bar': -1,
  'foobar': 21,
};

// myMap without negative values
myMap.entries.whereValue((v) => v >= 0).toMap();

// myMap, but only keys that start with 'foo'
myMap.entries.whereKey((k) => k.startsWith('foo')).toMap();
```
  • Loading branch information
jonasfj committed Nov 1, 2024
1 parent 9ad6888 commit 672e51a
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
4 changes: 4 additions & 0 deletions pkgs/collection/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.19.1-wip
- Add `IterableMapEntryExtension` for working on `Map` as a list of pairs, using
`Map.entries`.

## 1.19.1

- Move to `dart-lang/core` monorepo.
Expand Down
27 changes: 27 additions & 0 deletions pkgs/collection/lib/src/iterable_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,33 @@ extension IterableIterableExtension<T> on Iterable<Iterable<T>> {
};
}

/// Extension on iterables of [MapEntry].
///
/// An [Iterable<MapEntry>] is obtained using [Map.entries], these extensions
/// make it easy to work on a [Map] as a list of pairs.
extension IterableMapEntryExtension<K, V> on Iterable<MapEntry<K, V>> {
/// Creates a new lazy [Iterable] with all elements whose [MapEntry.key]
/// satisfy the predicate [test].
Iterable<MapEntry<K, V>> whereKey(bool Function(K) test) =>
where((e) => test(e.key));

/// Creates a new lazy [Iterable] with all elements whose [MapEntry.value]
/// satisfy the predicate [test].
Iterable<MapEntry<K, V>> whereValue(bool Function(V) test) =>
where((e) => test(e.value));

/// Create an new lazy [Iterable] with [MapEntry.key] from all elements.
Iterable<K> get keys => map((e) => e.key);

/// Create an new lazy [Iterable] with [MapEntry.value] from all elements.
Iterable<V> get values => map((e) => e.value);

/// Create a [Map] from all elements.
///
/// This is a short-hand for [Map.fromEntries].
Map<K, V> toMap() => Map.fromEntries(this);
}

/// Extensions that apply to iterables of [Comparable] elements.
///
/// These operations can assume that the elements have a natural ordering,
Expand Down
2 changes: 1 addition & 1 deletion pkgs/collection/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: collection
version: 1.19.1
version: 1.19.1-wip
description: >-
Collections and utilities functions and classes related to collections.
repository: https://github.com/dart-lang/core/tree/main/pkgs/collection
Expand Down
81 changes: 81 additions & 0 deletions pkgs/collection/test/extensions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,87 @@ void main() {
});
});
});
group('of MapEntry', () {
group('.whereKey', () {
test('empty', () {
expect(<String, int>{}.entries.whereKey(unreachable), isEmpty);
});
test('single', () {
expect({'a': 1}.entries.whereKey((k) => k == 'a').toMap(), {'a': 1});
expect({'a': 1}.entries.whereKey((k) => k == 'b').toMap(), isEmpty);
});
test('multiple', () {
expect(
{'a': 1, 'b': 2}.entries.whereKey((k) => k == 'a').toMap(),
{'a': 1},
);
expect(
{'a': 1, 'b': 2}.entries.whereKey((k) => k == 'b').toMap(),
{'b': 2},
);
expect(
{'a': 1, 'b': 2}.entries.whereKey((k) => k != 'c').toMap(),
{'a': 1, 'b': 2},
);
});
});
group('.whereValue', () {
test('empty', () {
expect(<String, int>{}.entries.whereValue(unreachable), isEmpty);
});
test('single', () {
expect({'a': 1}.entries.whereValue((v) => v == 1).toMap(), {'a': 1});
expect({'a': 1}.entries.whereValue((v) => v == 2).toMap(), isEmpty);
});
test('multiple', () {
expect(
{'a': 1, 'b': 2}.entries.whereValue((v) => v == 1).toMap(),
{'a': 1},
);
expect(
{'a': 1, 'b': 2}.entries.whereValue((v) => v == 2).toMap(),
{'b': 2},
);
expect(
{'a': 1, 'b': 2}.entries.whereValue((v) => v != 3).toMap(),
{'a': 1, 'b': 2},
);
});
});
group('.keys', () {
test('empty', () {
expect(<String, int>{}.entries.keys, isEmpty);
});
test('single', () {
expect({'a': 1}.entries.keys, ['a']);
});
test('multiple', () {
expect({'a': 1, 'b': 2}.entries.keys, ['a', 'b']);
});
});
group('.values', () {
test('empty', () {
expect(<String, int>{}.entries.values, isEmpty);
});
test('single', () {
expect({'a': 1}.entries.values, [1]);
});
test('multiple', () {
expect({'a': 1, 'b': 2}.entries.values, [1, 2]);
});
});
group('.toMap', () {
test('empty', () {
expect(<String, int>{}.entries.toMap(), <String, int>{});
});
test('single', () {
expect({'a': 1}.entries.toMap(), {'a': 1});
});
test('multiple', () {
expect({'a': 1, 'b': 2}.entries.toMap(), {'a': 1, 'b': 2});
});
});
});
group('of comparable', () {
group('.min', () {
test('empty', () {
Expand Down

0 comments on commit 672e51a

Please sign in to comment.