Skip to content

Commit

Permalink
Add onEachIndexed and make onEach chainable (#142)
Browse files Browse the repository at this point in the history
* Add onEachIndex and make onEach chainable

* Fix formatting

* Add set and list overrides
  • Loading branch information
passsy authored May 24, 2021
1 parent 8d6d217 commit 9284057
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 15 deletions.
44 changes: 29 additions & 15 deletions lib/src/collection/kt_iterable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1118,21 +1118,6 @@ extension KtIterableExtensions<T> on KtIterable<T> {
return true;
}

/// Performs the given [action] on each element. Use with cascade syntax to return self.
///
/// (listOf("a", "b", "c")
/// ..onEach(print))
/// .map((it) => it.toUpperCase())
/// .getOrNull(0); // prints: a
///
// ignore: comment_references
/// Without the cascade syntax (..) [KtListExtensions.getOrNull] wouldn't be available.
void onEach(void Function(T) action) {
for (final element in iter) {
action(element);
}
}

/// Splits the original collection into pair of lists,
/// where *first* list contains elements for which [predicate] yielded `true`,
/// while *second* list contains elements for which [predicate] yielded `false`.
Expand Down Expand Up @@ -1515,6 +1500,35 @@ extension RequireNoNullsKtIterableExtension<T> on KtIterable<T?> {
}
}

// TODO: Should be <T, C extends KtIterable<T>> on C but then T resolves to dynamic
// https://github.com/dart-lang/sdk/issues/46117
extension ChainableKtIterableExtensions<T> on KtIterable<T> {
/// Performs the given [action] on each element. Use with cascade syntax to return self.
///
/// final result = listOf("a", "b", "c")
/// .onEach(print)
/// .map((it) => it.toUpperCase())
/// .getOrNull(0);
/// // result: A
///
/// Without the cascade syntax (..) [KtListExtensions.getOrNull] wouldn't be available.
KtIterable<T> onEach(void Function(T item) action) {
for (final element in iter) {
action(element);
}
return this;
}

/// Performs the given action on each element, providing sequential index with the element, and returns the collection itself afterwards.
KtIterable<T> onEachIndexed(void Function(int index, T item) action) {
var index = 0;
for (final item in iter) {
action(index++, item);
}
return this;
}
}

class _MovingSubList<T> {
_MovingSubList(this.list);

Expand Down
28 changes: 28 additions & 0 deletions lib/src/collection/kt_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,34 @@ extension NullableKtListExtensions<T> on KtList<T>? {
KtList<T> orEmpty() => this ?? KtList<T>.empty();
}

// TODO remove in favor of ChainableKtIterableExtensions once https://github.com/dart-lang/sdk/issues/46117 is resolved
extension ChainableKtListExtensions<T> on KtList<T> {
/// Performs the given [action] on each element. Use with cascade syntax to return self.
///
/// final result = listOf("a", "b", "c")
/// .onEach(print)
/// .map((it) => it.toUpperCase())
/// .getOrNull(0);
/// // result: A
///
/// Without the cascade syntax (..) [KtListExtensions.getOrNull] wouldn't be available.
KtList<T> onEach(void Function(T item) action) {
for (final element in iter) {
action(element);
}
return this;
}

/// Performs the given action on each element, providing sequential index with the element, and returns the collection itself afterwards.
KtList<T> onEachIndexed(void Function(int index, T item) action) {
var index = 0;
for (final item in iter) {
action(index++, item);
}
return this;
}
}

extension RequireNoNullsKtListExtension<T> on KtList<T?> {
/// Returns an original collection containing all the non-`null` elements, throwing an [ArgumentError] if there are any `null` elements.
KtList<T> requireNoNulls() {
Expand Down
28 changes: 28 additions & 0 deletions lib/src/collection/kt_set.dart
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,31 @@ extension NullableKtSetExtensions<T> on KtSet<T>? {
/// Returns this [KtSet] if it's not `null` and the empty set otherwise.
KtSet<T> orEmpty() => this ?? KtSet<T>.empty();
}

// TODO remove in favor of ChainableKtIterableExtensions once https://github.com/dart-lang/sdk/issues/46117 is resolved
extension ChainableKtSetExtensions<T> on KtSet<T> {
/// Performs the given [action] on each element. Use with cascade syntax to return self.
///
/// final result = setOf("a", "b", "c")
/// .onEach(print)
/// .map((it) => it.toUpperCase())
/// .getOrNull(0);
/// // result: A
///
/// Without the cascade syntax (..) [KtListExtensions.getOrNull] wouldn't be available.
KtSet<T> onEach(void Function(T item) action) {
for (final element in iter) {
action(element);
}
return this;
}

/// Performs the given action on each element, providing sequential index with the element, and returns the collection itself afterwards.
KtSet<T> onEachIndexed(void Function(int index, T item) action) {
var index = 0;
for (final item in iter) {
action(index++, item);
}
return this;
}
}
39 changes: 39 additions & 0 deletions test/collection/iterable_extensions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,45 @@ void testIterable(KtIterable<T> Function<T>() emptyIterable,
iterable.onEach((it) => it.add(0));
expect(iterable.map((it) => it.last).toList(), listOf(0, 0, 0));
});

test("chainable", () {
final list = KtMutableList.empty();
final result = listOf("a", "b", "c")
.onEach((it) => list.add(it))
.map((it) => it.toUpperCase())
.getOrNull(0); // prints: A
expect(result, "A");
expect(list, listOf("a", "b", "c"));
});
});

group("onEachIndexed", () {
test("pairs", () {
final indexes = KtMutableList<int>.empty();
final items = KtMutableList<int>.empty();
final iterable = iterableOf([1, 2, 3]);
iterable.onEachIndexed((index, item) {
indexes.add(index);
items.add(item);
});
expect(indexes, listOf(0, 1, 2));
if (ordered) {
expect(items, iterable.toList());
}
});

test("chainable", () {
final list = KtMutableList.empty();
final result = listOf("a", "b", "c")
.onEachIndexed((index, it) {
list.add(index);
list.add(it);
})
.map((it) => it.toUpperCase())
.getOrNull(0); // prints: A
expect(result, "A");
expect(list, listOf(0, "a", 1, "b", 2, "c"));
});
});

group("partition", () {
Expand Down

0 comments on commit 9284057

Please sign in to comment.