Reputation: 3025
I have two lists, lst1
and lst2
. I want to perform lst1 - lst2
, which returns all elements of lst1
not in lst2
.
var lst1 = ["t1" , "t2" , "t3" , "t4"];
var lst2 = ["t2" , "t4" , "t5"];
//output: ["t1" , "t3"]
Upvotes: 16
Views: 7775
Reputation: 2541
solutions with sets are quite working. however, it is worth remembering that if you have a set of objects, then you need overloading operator == and hashCode in these objects.
Upvotes: 0
Reputation: 2033
var lst1 = ["t1" , "t2" , "t3" , "t4"];
var lst2 = ["t2" , "t4" , "t5"];
lst1 = lst1.removeWhere((item) => lst2!.contains(item));
Upvotes: 1
Reputation: 3019
If you want to do this in a non-destructive way and preserve the order, you can create an Iterable extension for this.
void main() {
final lst1 = ["t1" , "t2" , "t3" , "t4"];
final lst2 = ["t2" , "t4" , "t5"];
final diff = lst1.whereNotIn(lst2).toList();
print(diff);
}
extension WhereNotInExt<T> on Iterable<T> {
Iterable<T> whereNotIn(Iterable<T> reject) {
final rejectSet = reject.toSet();
return where((el) => !rejectSet.contains(el));
}
}
Try it out here: https://dartpad.dev/88c5c949b6ac8c2d0812e15ce10e40ce?null_safety=true
Some benefits to this approach:
Upvotes: 2
Reputation: 88378
Convert to sets and take the difference, then convert back to a list (with the caveat that neither duplicates nor the ordering of elements will be preserved):
void main() {
var lst1 = ["t1" , "t2" , "t3" , "t4"];
var lst2 = ["t2" , "t4" , "t5"];
var set1 = Set.from(lst1);
var set2 = Set.from(lst2);
print(List.from(set1.difference(set2)));
}
Output
[t1, t3]
Upvotes: 16
Reputation: 99
The method using sets suggested by Ray Toal is probably the fastest, but if your first list contains duplicates that you want to keep, sets will completely destroy them.
Instead, you could use a simple list filtering method.
void main() {
var lst1 = ["t1" , "t2" , "t2", "t3" , "t3", "t4"]; // introduce duplicates
var lst2 = ["t2" , "t4" , "t5"];
var set1 = Set.from(lst1);
var set2 = Set.from(lst2);
print(List.from(set1.difference(set2)));
// Output : [t1, t3]
var filtered_lst = List.from(lst1.where(
(value) => !lst2.contains(value)));
print(filtered_lst);
// Output: [t1, t3, t3]
}
If there is duplicates in both lists and you actually want to subtract list item per item, you could use the remove
method (warning: this will actually remove items from your first list, so you might need to create a copy first).
void main() {
var lst1 = ["t1" , "t2" , "t2", "t3" , "t3", "t4"]; // introduce duplicates
var lst2 = ["t2" , "t4" , "t5"];
for (var elem in lst2) {
lst1.remove(elem);
}
print(lst1);
// Output : [t1, t2, t3, t3]
// only one occurrence of "t2" was removed.
}
Upvotes: 8