Skip to main content

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.

tip

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
Common Mistake: Comparing sort() Return Values

sort() 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
note

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
Length Mismatch with 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

MethodOrder MattersHandles DuplicatesBest For
==✅ Yes✅ YesExact equality (content + order)
sorted() + ==❌ No✅ YesSame elements regardless of order
Counter()❌ No✅ YesFrequency-aware comparison
set()❌ No❌ Ignores duplicatesUnique element comparison
all() + zip()✅ Yes✅ YesPosition-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() with zip() 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.