From f1929987a4c95a9cf5f28d3b623de6428484ea82 Mon Sep 17 00:00:00 2001 From: Abbas Date: Mon, 1 Sep 2025 11:24:27 +0330 Subject: [PATCH 1/2] Add `intersperse` method to Iterable extension for efficient element separation Implement a new `intersperse` method that lazily inserts a specified separator between elements of an iterable. This method is memory-efficient and utilizes a generator for performance. Include comprehensive tests covering various scenarios, including empty iterables and different separator types. --- .../lib/src/iterable_extensions.dart | 27 +++++++++++++++++++ pkgs/collection/test/extensions_test.dart | 27 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/pkgs/collection/lib/src/iterable_extensions.dart b/pkgs/collection/lib/src/iterable_extensions.dart index d9516e67..53f18908 100644 --- a/pkgs/collection/lib/src/iterable_extensions.dart +++ b/pkgs/collection/lib/src/iterable_extensions.dart @@ -613,6 +613,33 @@ extension IterableExtension on Iterable { yield slice; } } + + /// Lazily returns a new iterable where a [separator] is placed between each + /// element of this iterable. + /// + /// This is the most performant way to implement this functionality because + /// it uses a generator (`sync*`) and does not create a new list upfront, + /// making it memory-efficient for iterables of any size. + /// + /// Example: + /// ```dart + /// final numbers = [1, 2, 3]; + /// final withSeparators = numbers.intersperse(0); + /// print(withSeparators.toList()); // Output: [1, 0, 2, 0, 3] + /// ``` + /// + /// The resulting iterable is lazy. It only computes the next value when + /// it's requested. + Iterable intersperse(T separator) sync* { + final iterator = this.iterator; + if (iterator.moveNext()) { + yield iterator.current; + while (iterator.moveNext()) { + yield separator; + yield iterator.current; + } + } + } } /// Extensions that apply to iterables with a nullable element type. diff --git a/pkgs/collection/test/extensions_test.dart b/pkgs/collection/test/extensions_test.dart index 16878a30..617291d3 100644 --- a/pkgs/collection/test/extensions_test.dart +++ b/pkgs/collection/test/extensions_test.dart @@ -1224,6 +1224,33 @@ void main() { ); }); }); + group('.intersperse', () { + test('empty', () { + expect(iterable([]).intersperse(0), []); + }); + test('single element', () { + expect(iterable([1]).intersperse(0), [1]); + }); + test('two elements', () { + expect(iterable([1, 2]).intersperse(0), [1, 0, 2]); + }); + test('multiple elements', () { + expect(iterable([1, 2, 3, 4]).intersperse(0), [1, 0, 2, 0, 3, 0, 4]); + }); + test('with different separator types', () { + expect(iterable(['a', 'b', 'c']).intersperse('-'), + ['a', '-', 'b', '-', 'c']); + expect(iterable([1.5, 2.5, 3.5]).intersperse(0.0), + [1.5, 0.0, 2.5, 0.0, 3.5]); + }); + test('with nullable int separator', () { + expect(iterable([1, 2, 3]).intersperse(0), [1, 0, 2, 0, 3]); + }); + test('with empty string separator', () { + expect(iterable(['a', 'b', 'c']).intersperse(''), + ['a', '', 'b', '', 'c']); + }); + }); }); group('of MapEntry', () { group('.whereKey', () { From e1999e98179a3f4fe9ce295be13162bf63f72ca4 Mon Sep 17 00:00:00 2001 From: Abbas Date: Mon, 1 Sep 2025 11:13:26 +0330 Subject: [PATCH 2/2] Add `intersperse` method to `IterableExtension` for efficient element separation --- pkgs/collection/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/collection/CHANGELOG.md b/pkgs/collection/CHANGELOG.md index 743fddf2..f2acb6b2 100644 --- a/pkgs/collection/CHANGELOG.md +++ b/pkgs/collection/CHANGELOG.md @@ -1,5 +1,6 @@ ## 1.20.0-wip +- Add `intersperse` method to `IterableExtension` for efficient element separation. - Add `IterableMapEntryExtension` for working on `Map` as a list of pairs, using `Map.entries`. - Explicitly mark `BoolList` as `abstract interface`