5 Best Ways to Check if Lists of Dicts Are Equal in Python

πŸ’‘ Problem Formulation: When working with lists of dictionaries in Python, it’s often necessary to verify whether two such lists are identical in terms of both structure and content. This can be important for tasks such as validating test cases or comparing configurations. Suppose you have two lists of dictionaries, list1 and list2. The goal is to ascertain if they represent the same data, regardless of the order of items within each dictionary or list. The desired outcome is a boolean result indicating equality.

Method 1: Using Deep Comparison with == Operator

The simplest way to compare if two lists of dictionaries are equal is by using the == operator. This method checks both the data and the order of the data within the lists. It is best used when you expect the order of dictionaries within the lists to be the same.

Here’s an example:

list1 = [{'a': 1}, {'b': 2}]
list2 = [{'a': 1}, {'b': 2}]
print(list1 == list2)

True

This code performs a deep comparison of two lists containing dictionaries. The == operator checks whether both lists contain the same dictionaries in the same order. Since list1 and list2 have dictionaries with identical keys and values, and in the same sequence, the result is True.

Method 2: Using all() with Sorted Lists

For lists of dictionaries where order does not matter, one approach involves sorting the lists and then using the all() function to verify that all corresponding dictionaries are equal. This method accounts for the same data arranged in a different order.

Here’s an example:

from operator import itemgetter

list1 = [{'b': 2}, {'a': 1}]
list2 = [{'a': 1}, {'b': 2}]
list1_sorted = sorted(list1, key=itemgetter('b'))
list2_sorted = sorted(list2, key=itemgetter('b'))

print(all(d1 == d2 for d1, d2 in zip(list1_sorted, list2_sorted)))

True

This snippet sorts two lists of dictionaries based on a key within the dictionaries before comparison. The sorted() function, combined with itemgetter(), sorts each list by the value associated with the key ‘b’. Afterward, zip() is used to create pairs of corresponding dictionaries, which are then compared using all() and the == operator. If all pairs are equal, the overall result is True.

Method 3: Using Set Operations with Frozensets

If the dictionaries inside the lists are hashable, they can be converted into frozensets and compared using set operations. This is effective if dictionaries are not nested and each dictionary can be converted into a set of items.

Here’s an example:

list1 = [{'a': 1}, {'b': 2}]
list2 = [{'b': 2}, {'a': 1}]
set1 = {frozenset(d.items()) for d in list1}
set2 = {frozenset(d.items()) for d in list2}
print(set1 == set2)

True

In the code sample, dictionaries are converted to frozensets of their items, making them hashable. Then, they’re added to a set comprehensions for both lists, resulting in two sets of frozensets. These sets are compared using the == operator. If they contain the same frozensets, the output is True, indicating that the original lists of dictionaries are equal in terms of content regardless of order.

Method 4: Using Serialization with JSON

This method checks for equality by serializing the list of dictionaries into strings using JSON, and then comparing the strings. The order of keys within the dictionaries is considered, so this method is effective if the contents and the order of the keys within the dictionaries should be the same.

Here’s an example:

import json

list1 = [{'a': 1}, {'b': 2}]
list2 = [{'a': 1}, {'b': 2}]

json1 = json.dumps(list1, sort_keys=True)
json2 = json.dumps(list2, sort_keys=True)

print(json1 == json2)

True

Each list of dictionaries is serialized to a JSON string using json.dumps(). The parameter sort_keys=True ensures that dictionaries are serialized with their keys sorted. Equality of the resulting JSON strings implies the two lists of dictionaries contain the same data in the same order, and therefore are equivalent.

Bonus One-Liner Method 5: Using Counter from collections

The Counter class from the collections module can treat each list of dictionaries as a multiset and perform comparison. Handy for simple, shallow dictionaries where the order of dictionaries in the list does not matter, and no nested structures are involved.

Here’s an example:

from collections import Counter

list1 = [{'a': 1}, {'b': 2}]
list2 = [{'b': 2}, {'a': 1}]

print(Counter(map(lambda d: tuple(d.items()), list1)) == Counter(map(lambda d: tuple(d.items()), list2)))

True

The Counter object counts occurrences of hashable objects, in this case, the items of each dictionary cast to tuples to make them hashable. By creating Counter objects from both lists and comparing them, we check if the lists contain the same dictionaries, regardless of the order within the list.

Summary/Discussion

  • Method 1: Simple Equality Check with ==. Strengths: Easy to use, no additional setup required. Weaknesses: Sensitive to the order of dictionaries and items within them.
  • Method 2: Comparison with Sorted Lists. Strengths: Ignores the order of dictionaries within the lists. Weaknesses: Requires all dictionaries to have the compared keys, and it can be less efficient due to sorting.
  • Method 3: Set Operations with Frozensets. Strengths: Order-independent and efficient for small to medium-sized lists of hashable dictionaries. Weaknesses: Not suitable for nested dictionaries or non-hashable dictionary items.
  • Method 4: Serialization with JSON. Strengths: Provides clear output and can handle nested structures. Weaknesses: Order-sensitive and may be less efficient for large data sets.
  • Method 5: Counter from collections. Strengths: Simple and concise for flat dictionaries. Weaknesses: Not suitable for nested structures or non-hashable items within the dictionaries.