diff --git a/lib/src/collection/extension/list_extension_mixin.dart b/lib/src/collection/extension/list_extension_mixin.dart index 9ff482af..59125912 100644 --- a/lib/src/collection/extension/list_extension_mixin.dart +++ b/lib/src/collection/extension/list_extension_mixin.dart @@ -263,4 +263,27 @@ abstract class KtListExtensionsMixin } return list; } + + @override + KtList takeLastWhile(bool Function(T) predicate) { + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); + if (isEmpty()) return emptyList(); + final iterator = listIterator(size); + while (iterator.hasPrevious()) { + if (!predicate(iterator.previous())) { + iterator.next(); + final expectedSize = size - iterator.nextIndex(); + if (expectedSize == 0) return emptyList(); + final list = mutableListOf(); + while (iterator.hasNext()) { + list.add(iterator.next()); + } + return list; + } + } + return toList(); + } } diff --git a/lib/src/collection/kt_list.dart b/lib/src/collection/kt_list.dart index efc82a0e..bbf3df4c 100644 --- a/lib/src/collection/kt_list.dart +++ b/lib/src/collection/kt_list.dart @@ -207,4 +207,9 @@ abstract class KtListExtension { * Returns a list containing last [n] elements. */ KtList takeLast(int n); + + /** + * Returns a list containing last elements satisfying the given [predicate]. + */ + KtList takeLastWhile(bool Function(T) predicate); } diff --git a/test/collection/iterable_extensions_test.dart b/test/collection/iterable_extensions_test.dart index 1e9cb666..7f5e3586 100644 --- a/test/collection/iterable_extensions_test.dart +++ b/test/collection/iterable_extensions_test.dart @@ -73,7 +73,7 @@ void testIterable(KtIterable Function() emptyIterable, test("predicate can't be null", () { final iterable = iterableOf(["abc", "bcd", "cde"]); final e = catchException(() => iterable.all(null)); - expect(e.message, allOf(contains("null"))); + expect(e.message, allOf(contains("predicate"), contains("null"))); }); }); diff --git a/test/collection/list_extensions_test.dart b/test/collection/list_extensions_test.dart index 5f10fb1d..d51c53bf 100644 --- a/test/collection/list_extensions_test.dart +++ b/test/collection/list_extensions_test.dart @@ -302,4 +302,43 @@ void testList( expect(list.takeLast(2).toList(), listFrom([1, null])); }); }); + + group("takeLastWhile", () { + test("take no elements returns empty", () { + final list = listOf(1, 2, 3, 4); + expect(list.takeLastWhile((it) => false), emptyList()); + }); + + test("take all elements returns original list", () { + final list = listOf(1, 2, 3, 4); + expect(list.takeLastWhile((it) => true), list.toList()); + }); + + if (ordered) { + test("takeLastWhile larger 2", () { + final list = listOf(1, 2, 3, 4); + expect(list.takeLastWhile((it) => it > 2), listOf(3, 4)); + }); + } + + if (ordered) { + test("takeLastWhile larger 1", () { + final list = listOf(1, 2, 3, 4); + expect(list.takeLastWhile((it) => it > 1), listOf(2, 3, 4)); + }); + } + + if (ordered) { + test("takeLastWhile larger 3", () { + final list = listOf(1, 2, 3, 4); + expect(list.takeLastWhile((it) => it > 3), listOf(4)); + }); + } + + test("predicate can't be null", () { + final list = listOf("a", "b", "c"); + final e = catchException(() => list.takeLastWhile(null)); + expect(e.message, allOf(contains("null"), contains("predicate"))); + }); + }); }