Add flattenedToList and flattenedToSet (#328)
For iterables which are known to be exhausted after flattening
performance is better than the `sync*` implementation using a collection
literal.
Add `flattenedToList` as a performance improvement over `flattened.`
Add `flattenedToSet` as new behavior for flattening to unique elements.
Originally implemented in
https://github.com/dart-lang/sdk/commit/8d3b6ce54ccb09dd970cd45fc3cded4a35beac31
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f93bdbc..d4b8cf7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@
generic.
- `CanonicalizedMap`: added constructor `fromEntries`.
- Mark "mixin" classes as `mixin`.
+- `extension IterableIterableExtension<T> on Iterable<Iterable<T>>`
+ - Add `flattenedToList` as a performance improvement over `flattened.`
+ - Add `flattenedToSet` as new behavior for flattening to unique elements.
- Deprecate `transitiveClosure`. Consider using `package:graphs`.
- Deprecate `whereNotNull()` from `IterableNullableExtension`. Use `nonNulls`
instead - this is an equivalent extension available in Dart core since
diff --git a/lib/src/iterable_extensions.dart b/lib/src/iterable_extensions.dart
index 0d52fbb..e205006 100644
--- a/lib/src/iterable_extensions.dart
+++ b/lib/src/iterable_extensions.dart
@@ -892,6 +892,26 @@
yield* elements;
}
}
+
+ /// The sequential elements of each iterable in this iterable.
+ ///
+ /// Iterates the elements of this iterable.
+ /// For each one, which is itself an iterable,
+ /// all the elements of that are added
+ /// to the returned list, before moving on to the next element.
+ List<T> get flattenedToList => [
+ for (final elements in this) ...elements,
+ ];
+
+ /// The unique sequential elements of each iterable in this iterable.
+ ///
+ /// Iterates the elements of this iterable.
+ /// For each one, which is itself an iterable,
+ /// all the elements of that are added
+ /// to the returned set, before moving on to the next element.
+ Set<T> get flattenedToSet => {
+ for (final elements in this) ...elements,
+ };
}
/// Extensions that apply to iterables of [Comparable] elements.
diff --git a/test/extensions_test.dart b/test/extensions_test.dart
index 6fa6e4a..9940e1d 100644
--- a/test/extensions_test.dart
+++ b/test/extensions_test.dart
@@ -1064,6 +1064,63 @@
[1, 2, 3, 4]);
});
});
+ group('.flattenedToList', () {
+ var empty = iterable(<int>[]);
+ test('empty', () {
+ expect(iterable(<Iterable<int>>[]).flattenedToList, []);
+ });
+ test('multiple empty', () {
+ expect(iterable([empty, empty, empty]).flattenedToList, []);
+ });
+ test('single value', () {
+ expect(
+ iterable(<Iterable>[
+ iterable([1])
+ ]).flattenedToList,
+ [1]);
+ });
+ test('multiple', () {
+ expect(
+ iterable(<Iterable>[
+ iterable([1, 2]),
+ empty,
+ iterable([3, 4])
+ ]).flattenedToList,
+ [1, 2, 3, 4]);
+ });
+ });
+ group('.flattenedToSet', () {
+ var empty = iterable(<int>[]);
+ test('empty', () {
+ expect(iterable(<Iterable<int>>[]).flattenedToSet, <int>{});
+ });
+ test('multiple empty', () {
+ expect(iterable([empty, empty, empty]).flattenedToSet, <int>{});
+ });
+ test('single value', () {
+ expect(
+ iterable(<Iterable>[
+ iterable([1])
+ ]).flattenedToSet,
+ {1});
+ });
+ test('multiple', () {
+ expect(
+ iterable(<Iterable>[
+ iterable([1, 2]),
+ empty,
+ iterable([3, 4])
+ ]).flattenedToSet,
+ {1, 2, 3, 4});
+ expect(
+ iterable(<Iterable>[
+ iterable([1, 2, 3]),
+ empty,
+ iterable([2, 3, 4])
+ ]).flattenedToSet,
+ {1, 2, 3, 4});
+ });
+ });
});
group('of comparable', () {
group('.min', () {