Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extension IteratorExt<T> on Iterable<T> {
- /// Returns [Iterable] that passes only unique elements.
- /// Elements is comparing by [keySelector].
- /// When some element repeats than [onDuplicate] calls to either ignore it
- /// (if [onDuplicate] is not provided or if it returns `null`)
- /// or replace with a new value.
- /// If element returning by [onDuplicate] is equals to original element or has
- /// a key that already exists it will be ignored.
- Iterable<T> distinctBy(Object Function(T) keySelector,
- {T Function(T old, T current) onDuplicate}) =>
- _DistinctIterable(this, keySelector, onDuplicate);
- }
- class _DistinctIterable<T> extends Iterable<T> {
- final Iterable<T> _iterable;
- final Object Function(T) _keySelector;
- final T Function(T old, T current) _onDuplicate;
- final Map<Object, T> uniqueElements = {};
- _DistinctIterable(
- this._iterable,
- this._keySelector,
- T Function(T, T) onDuplicate,
- ) : _onDuplicate = onDuplicate ?? ((old, curr) => null);
- Iterator<T> get iterator {
- _iterable.forEach((element) {
- final key = _keySelector(element);
- final old = uniqueElements[key];
- if (old != null) {
- final value = _onDuplicate(old, element);
- if (value != null) uniqueElements[_keySelector(value)] = value;
- } else
- uniqueElements[key] = element;
- });
- return uniqueElements.values.iterator;
- }
- }
- void main() {
- // 1, 3, 5
- print([1, 3, 5, 1, 5].distinctBy((i) => i).join(", "));
- // 1, 3, 5, 2, 10
- print(
- [1, 3, 5, 1, 5].distinctBy((i) => i, onDuplicate: (old, current ) => old + current).join(", "));
- final collection = [
- KeyValuePair("A", 1),
- KeyValuePair("B", 3),
- KeyValuePair("C", 5),
- KeyValuePair("D", 1),
- KeyValuePair("E", 5),
- ];
- // [A, 1], [B, 3], [C, 5]
- print(collection.distinctBy((obj) => obj.value).join(", "));
- // [A, 1], [B, 3], [C, 5], [D (duplicated from A), 2], [E (duplicated from C), 10]
- print(collection
- .distinctBy((obj) => obj.value,
- onDuplicate: (old, current) => KeyValuePair(
- "${current.key} (duplicated from ${old.key})",
- old.value + current.value,
- ))
- .join(", "));
- }
- class KeyValuePair {
- final String key;
- final int value;
- const KeyValuePair(this.key, this.value);
- @override
- String toString() => "[$key, $value]";
- @override
- bool operator ==(Object other) =>
- identical(this, other) ||
- other is KeyValuePair &&
- runtimeType == other.runtimeType &&
- key == other.key &&
- value == other.value;
- @override
- int get hashCode => key.hashCode ^ value.hashCode;
- }
Add Comment
Please, Sign In to add comment