How do i delete duplicates from a list without fooling around with a set? Is there something like list.distinct()? or list.unique()?
void main() {
print(\"
I have a library called Reactive-Dart that contains many composable operators for terminating and non-terminating sequences. For your scenario it would look something like this:
final newList = [];
Observable
.fromList(['abc', 'abc', 'def'])
.distinct()
.observe((next) => newList.add(next), () => print(newList));
Yielding:
[abc, def]
I should add that there are other libraries out there with similar features. Check around on github and I'm sure you'll find something suitable.
Here it is working solution:
var sampleList = ['1', '2', '3', '3', '4', '4'];
//print('orignal: $sampleList');
sampleList = Set.of(sampleList).toList();
//print('processed: $sampleList');
Output:
orignal: [1, 2, 3, 3, 4, 4]
processed: [1, 2, 3, 4]
I didn't find any of the provided answers very helpful. Here is what I generally do:
final ids = myList.map((e) => e.id).toSet();
myList.retainWhere((x) => ids.remove(x.id));
Of course you can use any attribute which uniquely identifies your objects, it doesn't have to be an id
field.
This approach is particularly useful for richer objects. For simple primitive types some of the answers already posted here are fine. Another nice side-effect of this solution is that unlike others provided here, this solution does not change the order of your original items in the list as it modifies the list in place!
As for me one of best practices is sort array, then deduplicate it. Idea is stolen from low level languages. So,
first make sort by your own, then deduplicate equal values that are going after each other.
// easy example
void dedup<T>(List<T> list, {removeLast: true}) {
int shift = removeLast ? 1 : 0;
T compareItem;
for (int i = list.length - 1; i >= 0; i--) {
if (compareItem == (compareItem = list[i])) {
list.removeAt(i + shift);
}
}
}
// harder example
void dedupBy<T, I>(List<T> list, I Function(T) compare, {removeLast: true}) {
int shift = removeLast ? 1 : 0;
I compareItem;
for (int i = list.length - 1; i >= 0; i--) {
if (compareItem == (compareItem = compare(list[i]))) {
list.removeAt(i + shift);
}
}
}
void main() {
List<List<int>> list = [[1], [1], [2, 1], [2, 2]];
print('$list');
dedupBy(list, (innerList) => innerList[0]);
print('$list');
print('\n removeLast: false');
List<List<int>> list2 = [[1], [1], [2, 1], [2, 2]];
print('$list2');
dedupBy(list2, (innerList) => innerList[0], removeLast: false);
print('$list2');
}
Output:
[[1], [1], [2, 1], [2, 2]]
[[1], [2, 1]]
removeLast: false
[[1], [1], [2, 1], [2, 2]]
[[1], [2, 2]]
this is other way...
final reducedList = [];
list.reduce((value, element) {
if (value != element) reducedList.add(value);
return element;
});
reducedList.add(list.last);
print(reducedList);
If you want to keep ordering or are dealing with more complex objects than primitive types. Store seen ids to the Set and filter away those ones that are already in the set.
final list = ['a', 'a', 'b'];
final seen = Set<String>();
final unique = list.where((str) => seen.add(str)).toList();
print(unique); // => ['a', 'b']