Skip to content

Commit 672e51a

Browse files
committed
Introduce IterableMapEntryExtension for use with Map.entries.
**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(); ```
1 parent 9ad6888 commit 672e51a

File tree

4 files changed

+113
-1
lines changed

4 files changed

+113
-1
lines changed

pkgs/collection/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.19.1-wip
2+
- Add `IterableMapEntryExtension` for working on `Map` as a list of pairs, using
3+
`Map.entries`.
4+
15
## 1.19.1
26

37
- Move to `dart-lang/core` monorepo.

pkgs/collection/lib/src/iterable_extensions.dart

+27
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,33 @@ extension IterableIterableExtension<T> on Iterable<Iterable<T>> {
914914
};
915915
}
916916

917+
/// Extension on iterables of [MapEntry].
918+
///
919+
/// An [Iterable<MapEntry>] is obtained using [Map.entries], these extensions
920+
/// make it easy to work on a [Map] as a list of pairs.
921+
extension IterableMapEntryExtension<K, V> on Iterable<MapEntry<K, V>> {
922+
/// Creates a new lazy [Iterable] with all elements whose [MapEntry.key]
923+
/// satisfy the predicate [test].
924+
Iterable<MapEntry<K, V>> whereKey(bool Function(K) test) =>
925+
where((e) => test(e.key));
926+
927+
/// Creates a new lazy [Iterable] with all elements whose [MapEntry.value]
928+
/// satisfy the predicate [test].
929+
Iterable<MapEntry<K, V>> whereValue(bool Function(V) test) =>
930+
where((e) => test(e.value));
931+
932+
/// Create an new lazy [Iterable] with [MapEntry.key] from all elements.
933+
Iterable<K> get keys => map((e) => e.key);
934+
935+
/// Create an new lazy [Iterable] with [MapEntry.value] from all elements.
936+
Iterable<V> get values => map((e) => e.value);
937+
938+
/// Create a [Map] from all elements.
939+
///
940+
/// This is a short-hand for [Map.fromEntries].
941+
Map<K, V> toMap() => Map.fromEntries(this);
942+
}
943+
917944
/// Extensions that apply to iterables of [Comparable] elements.
918945
///
919946
/// These operations can assume that the elements have a natural ordering,

pkgs/collection/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: collection
2-
version: 1.19.1
2+
version: 1.19.1-wip
33
description: >-
44
Collections and utilities functions and classes related to collections.
55
repository: https://github.com/dart-lang/core/tree/main/pkgs/collection

pkgs/collection/test/extensions_test.dart

+81
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,87 @@ void main() {
11221122
});
11231123
});
11241124
});
1125+
group('of MapEntry', () {
1126+
group('.whereKey', () {
1127+
test('empty', () {
1128+
expect(<String, int>{}.entries.whereKey(unreachable), isEmpty);
1129+
});
1130+
test('single', () {
1131+
expect({'a': 1}.entries.whereKey((k) => k == 'a').toMap(), {'a': 1});
1132+
expect({'a': 1}.entries.whereKey((k) => k == 'b').toMap(), isEmpty);
1133+
});
1134+
test('multiple', () {
1135+
expect(
1136+
{'a': 1, 'b': 2}.entries.whereKey((k) => k == 'a').toMap(),
1137+
{'a': 1},
1138+
);
1139+
expect(
1140+
{'a': 1, 'b': 2}.entries.whereKey((k) => k == 'b').toMap(),
1141+
{'b': 2},
1142+
);
1143+
expect(
1144+
{'a': 1, 'b': 2}.entries.whereKey((k) => k != 'c').toMap(),
1145+
{'a': 1, 'b': 2},
1146+
);
1147+
});
1148+
});
1149+
group('.whereValue', () {
1150+
test('empty', () {
1151+
expect(<String, int>{}.entries.whereValue(unreachable), isEmpty);
1152+
});
1153+
test('single', () {
1154+
expect({'a': 1}.entries.whereValue((v) => v == 1).toMap(), {'a': 1});
1155+
expect({'a': 1}.entries.whereValue((v) => v == 2).toMap(), isEmpty);
1156+
});
1157+
test('multiple', () {
1158+
expect(
1159+
{'a': 1, 'b': 2}.entries.whereValue((v) => v == 1).toMap(),
1160+
{'a': 1},
1161+
);
1162+
expect(
1163+
{'a': 1, 'b': 2}.entries.whereValue((v) => v == 2).toMap(),
1164+
{'b': 2},
1165+
);
1166+
expect(
1167+
{'a': 1, 'b': 2}.entries.whereValue((v) => v != 3).toMap(),
1168+
{'a': 1, 'b': 2},
1169+
);
1170+
});
1171+
});
1172+
group('.keys', () {
1173+
test('empty', () {
1174+
expect(<String, int>{}.entries.keys, isEmpty);
1175+
});
1176+
test('single', () {
1177+
expect({'a': 1}.entries.keys, ['a']);
1178+
});
1179+
test('multiple', () {
1180+
expect({'a': 1, 'b': 2}.entries.keys, ['a', 'b']);
1181+
});
1182+
});
1183+
group('.values', () {
1184+
test('empty', () {
1185+
expect(<String, int>{}.entries.values, isEmpty);
1186+
});
1187+
test('single', () {
1188+
expect({'a': 1}.entries.values, [1]);
1189+
});
1190+
test('multiple', () {
1191+
expect({'a': 1, 'b': 2}.entries.values, [1, 2]);
1192+
});
1193+
});
1194+
group('.toMap', () {
1195+
test('empty', () {
1196+
expect(<String, int>{}.entries.toMap(), <String, int>{});
1197+
});
1198+
test('single', () {
1199+
expect({'a': 1}.entries.toMap(), {'a': 1});
1200+
});
1201+
test('multiple', () {
1202+
expect({'a': 1, 'b': 2}.entries.toMap(), {'a': 1, 'b': 2});
1203+
});
1204+
});
1205+
});
11251206
group('of comparable', () {
11261207
group('.min', () {
11271208
test('empty', () {

0 commit comments

Comments
 (0)