Dart/Flutter - Get Difference Between Two Lists

This tutorial shows you how to find the difference of elements between two Lists in Dart.

If you have two Lists 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 Lists 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 in l2: ['grass', 'grass']
  • Elements in l2 not in l1: ['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 Lists to Sets. 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 Lists 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 Lists 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 Lists 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: