This tutorial shows you how to find the difference of elements between two List
s in Dart.
If you have two List
s and you want to find what elements are present in a List
but not in the other one, you can read the examples in this tutorial. Below are the List
s that we are going to find the difference.
final l1 = ['grass', 'water', 'fire', 'grass'];
final l2 = ['water', 'fire', 'dragon', 'fairy'];
In this tutorial, we are going to find the elements in l1
that are not in l2
and the other way around. The expected output is:
- Elements in
l1
not inl2
:['grass', 'grass']
- Elements in
l2
not inl1
:['dragon', 'fairy']
Using Loop
Since a List
is an Iterable
, you can use a for loop to iterate the elements. Then, check whether the element exists in the other List
. If it doesn't exist, the element should be included in the result.
List<T> differenceWithLoop<T>(List<T> a, List<T> b) {
final List<T> result = [];
for (T element in a) {
if (!b.contains(element)) {
result.add(element);
}
}
return result;
}
print(differenceWithLoop(l1, l2));
print(differenceWithLoop(l2, l1));
Output:
[grass, grass]
[dragon, fairy]
Using where
Dart's Iterable
has a where
operator which is used to create an Iterable
whose elements match the passed predicate function. For this case, we can create a predicate function that returns true
if the element doesn't exist in the other List
.
List<T> differenceWithWhere<T>(List<T> a, List<T> b) {
return a.where((element) => !b.contains(element)).toList();
}
print(differenceWithLoop(l1, l2));
print(differenceWithLoop(l2, l1));
Output:
[grass, grass]
[dragon, fairy]
Using Set.difference
Another idea is by converting the List
s to Set
s. Set
has a method named difference
which returns a new Set
with the elements of the current Set
that are not in the other Set
passed as the argument. A List
can be converted to a Set
by using toSet
method. Because converted to a Set
, the duplicate elements can only appear at most once in the result.
List<T> differenceWithSet<T>(List<T> a, List<T> b) {
return a.toSet().difference(b.toSet()).toList();
}
print(differenceWithLoop(l1, l2));
print(differenceWithLoop(l2, l1));
Output:
[grass]
[dragon, fairy]
Find Difference Between Lists of Mutable Objects
If the elements contain mutable objects, you may need to understand how object comparison works. The Iterable.contains
and Set.difference
use the equality operator to compare the elements.
For example, there is a class named Item
with two fields as shown below.
class Item {
String name;
double price;
Item({
required this.name,
required this.price,
});
}
Then, we create two List
s of Item
instances and try to find the difference using any of the methods above.
final Item item1a = Item(name: 'A', price: 100);
final Item item1b = Item(name: 'B', price: 200);
List<Item> items = [item1a, item1b];
final Item item2a = Item(name: 'A', price: 100);
final Item item2b = Item(name: 'B', price: 200);
List<Item> items2 = [item2a, item2b];
print(differenceWithLoop(items, items2));
Output
[(name: A, price: 100.0), (name: B, price: 200.0), (name: C, price: 300.0)] // all items are considered different
From the output, we can see that all instances in the first List
are considered not found in the second List
, even though the first two instances of the first List
have the corresponding instance in the second List
with the same values for all fields. That's because the equality operator compares the objects based on the memory reference by default. You can read the details in our tutorial about object comparison in Dart.
If you want to make the objects compared by the values of the fields, a possible solution is by overriding the equality operator. If you do that, you also have to override the hashCode
property.
class Item {
String name;
double price;
Item({
required this.name,
required this.price,
});
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
return (other is Item
&& other.runtimeType == runtimeType
&& other.name == name
&& other.price == price
);
}
@override
int get hashCode => Object.hash(name.hashCode, price.hashCode);
}
After overriding the equality operator, the result will be different since two Item
instances with the same name
and price
are considered equal. Another alternative is canonicalizing the instances by using const constructor.
Output
[(name: C, price: 300.0)]// only the third item is considered different
Summary
There are several ways to get the difference between two List
s in Dart. You can iterate using for loop or filter using where
to find the elements that are not in the other List
. Another way is converting the List
s to Set
and use the difference
method. If the List
contains mutable objects, you may consider overriding the equality operator if necessary.
You can also read about: