python
lists
equality
algorithms
programming

Check if two unordered lists are equal

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To check whether two unordered lists are equal, you first need to decide whether duplicates matter. If duplicates count, then you are really comparing multisets. If duplicates do not count, then you are comparing sets.

That distinction changes the implementation completely. Many wrong answers come from using set on lists that may contain repeated values, which silently drops duplicates and produces false positives.

If Duplicates Matter, Compare Element Counts

For most problems, this is the correct interpretation. The lists are equal if they contain the same elements with the same frequencies, regardless of order.

In Python, collections.Counter is the cleanest tool for that job:

python
1from collections import Counter
2
3
4def unordered_equal(a: list[int], b: list[int]) -> bool:
5    return Counter(a) == Counter(b)
6
7
8print(unordered_equal([1, 2, 2, 3], [3, 2, 1, 2]))  # True
9print(unordered_equal([1, 2, 2], [1, 2, 3]))        # False
10print(unordered_equal([1, 1, 2], [1, 2, 2]))        # False

Counter works by storing each distinct value and how many times it appears. That makes the intent obvious and handles duplicate-heavy lists correctly.

The time complexity is typically O(n) and the extra memory is also O(n) in the number of distinct values.

Sorting Is Another Correct Option

If the elements are sortable, you can sort both lists and compare the results:

python
1def unordered_equal_sorted(a: list[int], b: list[int]) -> bool:
2    return sorted(a) == sorted(b)
3
4
5print(unordered_equal_sorted(["b", "a", "a"], ["a", "b", "a"]))  # True

This is also correct when duplicates matter, because repeated values remain present after sorting. The tradeoff is performance: sorting costs O(n log n) time.

For small lists, the difference is usually irrelevant. For large lists or streaming-like workloads, Counter is often the better choice.

Use set Only If Duplicates Do Not Matter

Sometimes the requirement is weaker: the lists should contain the same unique values, and multiplicity is irrelevant. In that case, set comparison is fine:

python
1def same_unique_values(a: list[int], b: list[int]) -> bool:
2    return set(a) == set(b)
3
4
5print(same_unique_values([1, 2, 2, 3], [3, 2, 1]))  # True

Notice what happened there: the first list contained two copies of 2, but the result is still True because sets discard duplicates. That is correct only if your specification says duplicates should be ignored.

What About Unhashable or Nested Elements

Counter and set require hashable elements. Plain integers, strings, and tuples are fine, but lists and dictionaries are not.

If your lists contain nested structures, you have a few options:

  • normalize the values into hashable tuples before comparing
  • sort by a stable key if the items are sortable after normalization
  • compare serialized representations only if you fully control the format

Example with dictionaries:

python
1from collections import Counter
2
3
4def freeze_user(user: dict) -> tuple:
5    return tuple(sorted(user.items()))
6
7
8left = [{"id": 1, "name": "Ana"}, {"id": 2, "name": "Bo"}]
9right = [{"name": "Bo", "id": 2}, {"name": "Ana", "id": 1}]
10
11print(Counter(map(freeze_user, left)) == Counter(map(freeze_user, right)))

The freezing step turns each dictionary into a comparable tuple of key-value pairs.

Common Pitfalls

  • Using set(a) == set(b) when duplicates matter. This is the most common mistake.
  • Sorting values that are not mutually comparable, such as mixed numbers and dictionaries.
  • Forgetting to normalize nested mutable objects before comparison.
  • Assuming list equality itself is enough. Plain a == b is order-sensitive.
  • Optimizing too early. For most code, the clearest correct solution is better than a trickier micro-optimization.

Summary

  • Decide first whether duplicates are significant.
  • If duplicates matter, compare multisets with Counter or with sorted lists.
  • If duplicates do not matter, set comparison is enough.
  • Normalize nested unhashable values before using Counter or set.
  • The right answer depends less on Python syntax and more on the exact definition of equality you need.

Course illustration
Course illustration

All Rights Reserved.