How to Compare Two Lists in Python
Comparing two lists is one of the most common operations in Python programming. Whether you're checking if two datasets are identical, finding differences between collections, or validating that a function produces the expected output, you need to understand the different ways lists can be compared, and when each approach is appropriate.
The key distinction is whether you care about element order. Two lists with the same elements in a different order might be considered equal or unequal depending on your use case. In this guide, you'll learn multiple methods to compare lists in Python, understand their differences, and choose the right one for your situation.
Direct Comparison with ==
The simplest way to compare two lists is the == operator. It checks if both lists have the same elements in the same order.
a = [1, 2, 3, 4, 5]
b = [1, 2, 3, 4, 5]
c = [5, 4, 3, 2, 1]
print(a == b) # Same elements, same order
print(a == c) # Same elements, different order
Output:
True
False
The == operator returns True only when both the content and order are identical. Lists a and c contain the same numbers, but since the order differs, they are not considered equal.
Direct == comparison is the best choice when order matters. For example, comparing sequences of events, ranked results, or sorted outputs.
Order-Independent Comparison with sorted()
When you want to check if two lists contain the same elements regardless of order, sort both lists first and then compare:
a = [1, 2, 3, 4, 5]
b = [5, 4, 3, 2, 1]
result = sorted(a) == sorted(b)
print(result)
Output:
True
sorted() returns a new sorted list without modifying the originals. After sorting, both lists have the same element order, so == returns True.
# Original lists remain unchanged
a = [3, 1, 2]
b = [2, 3, 1]
print(sorted(a) == sorted(b))
print(f"a is still: {a}")
print(f"b is still: {b}")
Output:
True
a is still: [3, 1, 2]
b is still: [2, 3, 1]
Using sort() (In-Place)
The sort() method sorts the list in place and returns None. Be careful with comparisons:
a = [3, 1, 2]
b = [2, 3, 1]
a.sort()
b.sort()
print(a == b)
Output:
True
sort() Return Valuessort() returns None, not the sorted list. Comparing return values directly always gives True (since None == None):
a = [1, 2, 3]
b = [9, 8, 7]
# ❌ Wrong: compares None == None, always True
print(a.sort() == b.sort())
Output:
True
This is a false positive: the lists have completely different elements. Always sort first, then compare:
a = [1, 2, 3]
b = [9, 8, 7]
a.sort()
b.sort()
# ✅ Correct: compares sorted lists
print(a == b)
Output:
False
Using collections.Counter() for Frequency-Aware Comparison
Counter from the collections module counts the occurrences of each element. This is the best method when order doesn't matter but duplicates do.
from collections import Counter
a = [1, 2, 2, 3]
b = [3, 2, 1, 2]
c = [1, 2, 3, 3]
print(Counter(a) == Counter(b)) # Same elements, same frequencies
print(Counter(a) == Counter(c)) # Different frequencies of 2 and 3
Output:
True
False
Counter correctly identifies that a and b have the same elements with the same frequencies (two 2s, one 1, one 3), while c has a different distribution.
Why Counter Is Better Than set for Duplicates
from collections import Counter
a = [1, 2, 2, 3]
b = [1, 2, 3]
print(f"set comparison: {set(a) == set(b)}")
print(f"Counter comparison: {Counter(a) == Counter(b)}")
Output:
set comparison: True
Counter comparison: False
set loses duplicate information, so it incorrectly reports the lists as equal. Counter preserves frequency counts and correctly identifies the difference.
Using set() for Unique Element Comparison
Convert both lists to sets when you want to check if they contain the same unique elements, ignoring both order and duplicates:
a = [1, 2, 2, 3, 3, 3]
b = [3, 2, 1]
print(set(a) == set(b))
Output:
True
set() discards duplicates. Use this method only when you intentionally want to ignore duplicate counts. For most comparison tasks, Counter or sorted() is more appropriate.
Finding Differences with Sets
Sets also make it easy to find elements that exist in one list but not the other:
a = [1, 2, 3, 4, 5]
b = [3, 4, 5, 6, 7]
set_a = set(a)
set_b = set(b)
print(f"Only in a: {set_a - set_b}")
print(f"Only in b: {set_b - set_a}")
print(f"In both: {set_a & set_b}")
Output:
Only in a: {1, 2}
Only in b: {6, 7}
In both: {3, 4, 5}
Element-Wise Comparison with all() and zip()
To compare corresponding elements at each position, use all() with zip(). This approach is useful when you need position-aware equality:
a = [1, 2, 3, 4, 5]
b = [1, 2, 3, 4, 5]
c = [1, 2, 99, 4, 5]
print(all(x == y for x, y in zip(a, b)))
print(all(x == y for x, y in zip(a, c)))
Output:
True
False
zip()zip() stops at the shorter list, which can produce false positives:
a = [1, 2, 3]
b = [1, 2, 3, 4, 5]
print(all(x == y for x, y in zip(a, b))) # True: ignores extra elements!
Output:
True
Add a length check or use zip_longest() for safety:
from itertools import zip_longest
a = [1, 2, 3]
b = [1, 2, 3, 4, 5]
# Safe version with length check
print(len(a) == len(b) and all(x == y for x, y in zip(a, b)))
# Or use zip_longest
sentinel = object()
print(all(x == y for x, y in zip_longest(a, b, fillvalue=sentinel)))
Output:
False
False
Practical Example: Finding What Changed
A common real-world task is comparing two versions of a list and identifying additions, removals, and common elements:
from collections import Counter
def compare_lists(list1, list2):
"""Compare two lists and return a detailed report."""
counter1 = Counter(list1)
counter2 = Counter(list2)
added = counter2 - counter1
removed = counter1 - counter2
common = counter1 & counter2
return {
'are_equal': counter1 == counter2,
'added': list(added.elements()),
'removed': list(removed.elements()),
'common': list(common.elements())
}
old_inventory = ['apple', 'banana', 'apple', 'cherry', 'date']
new_inventory = ['apple', 'banana', 'cherry', 'cherry', 'elderberry']
result = compare_lists(old_inventory, new_inventory)
print(f"Equal: {result['are_equal']}")
print(f"Added: {result['added']}")
print(f"Removed: {result['removed']}")
print(f"Common: {result['common']}")
Output:
Equal: False
Added: ['cherry', 'elderberry']
Removed: ['apple', 'date']
Common: ['apple', 'banana', 'cherry']
Quick Comparison of Methods
| Method | Order Matters | Handles Duplicates | Best For |
|---|---|---|---|
== | ✅ Yes | ✅ Yes | Exact equality (content + order) |
sorted() + == | ❌ No | ✅ Yes | Same elements regardless of order |
Counter() | ❌ No | ✅ Yes | Frequency-aware comparison |
set() | ❌ No | ❌ Ignores duplicates | Unique element comparison |
all() + zip() | ✅ Yes | ✅ Yes | Position-by-position comparison |
Conclusion
Python offers several ways to compare two lists, and choosing the right method depends on what "equal" means for your use case:
- Use
==when both order and content must match exactly. The simplest and most common choice. - Use
sorted()when you want to ignore order but still account for duplicates. - Use
Counter()for the most robust order-independent comparison that correctly handles duplicate elements. - Use
set()only when you want to compare unique elements and intentionally ignore duplicates. - Use
all()withzip()for element-wise positional comparison, but always add a length check to avoid silent mismatches.
For most everyday comparisons, == or sorted() will be sufficient. When working with data that may contain duplicates and order variation, Counter() is the safest and most reliable choice.