Mohammad Nazari
Mohammad Nazari

Reputation: 3025

remove list from another list in dart

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

Answers (5)

Vladyslav Ulianytskyi
Vladyslav Ulianytskyi

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

Mohammad Reza Mrg
Mohammad Reza Mrg

Reputation: 2033

var lst1 = ["t1" , "t2" , "t3" , "t4"];
var lst2 = ["t2" , "t4" , "t5"];

lst1 = lst1.removeWhere((item) => lst2!.contains(item));

Upvotes: 1

Venkat D.
Venkat D.

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:

  • Doesn't mutate the original list
  • Preserves the original order
  • Works on Iterable too
  • It uses a set to keep track of the elements to reject, so it doesn't slow down a lot if both lists are large

Upvotes: 2

Ray Toal
Ray Toal

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]

Try it online

Upvotes: 16

Jquenel
Jquenel

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

Related Questions