From 22c3c5e0d12696f8822bd6a06aabd0db84f7afc6 Mon Sep 17 00:00:00 2001 From: Marc Plano-Lesay Date: Mon, 25 Oct 2021 14:58:31 +1100 Subject: [PATCH] Introduce a new lastBy() function Similar to groupBy(), except that it only keeps the latest value corresponding to a given key. Prior art: [Kotlin](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/associate-by.html) --- CHANGELOG.md | 4 ++++ lib/src/functions.dart | 13 +++++++++++++ test/functions_test.dart | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 806a8b0..c1f049e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.16.1-dev +* Add a top-level `lastBy()` function that converts an `Iterable` to a `Map` by + grouping its elements using a function, keeping the last element for each + computed key. + ## 1.16.0 * Add an `Iterable.slices` extension method. diff --git a/lib/src/functions.dart b/lib/src/functions.dart index 64a38ee..2a799cf 100644 --- a/lib/src/functions.dart +++ b/lib/src/functions.dart @@ -41,6 +41,19 @@ Map mergeMaps(Map map1, Map map2, return result; } +/// Associates the elements in [values] by the value returned by [key]. +/// +/// Returns a map from keys computed by [key] to the last value for which [key] +/// returns that key. +Map lastBy(Iterable values, T Function(S) key) { + var map = {}; + for (var element in values) { + map[key(element)] = element; + } + + return map; +} + /// Groups the elements in [values] by the value returned by [key]. /// /// Returns a map from keys computed by [key] to a list of all values for which diff --git a/test/functions_test.dart b/test/functions_test.dart index 97bb4ab..d032b8b 100644 --- a/test/functions_test.dart +++ b/test/functions_test.dart @@ -79,6 +79,23 @@ void main() { }); }); + group('lastBy()', () { + test('returns an empty map for an empty iterable', () { + expect(lastBy([], expectAsync1((dynamic _) {}, count: 0)), isEmpty); + }); + + test("keeps the latest element for the function's return value", () { + expect( + lastBy(['foo', 'bar', 'baz', 'bop', 'qux'], + (String string) => string[1]), + equals({ + 'o': 'bop', + 'a': 'baz', + 'u': 'qux', + })); + }); + }); + group('groupBy()', () { test('returns an empty map for an empty iterable', () { expect(groupBy([], expectAsync1((dynamic _) {}, count: 0)), isEmpty);