Skip to main content

How to Check if a List Contains All Unique Elements in Python

Determining whether a list contains all unique elements (no duplicates) is a common task in data validation, input processing, and algorithm design. Whether you're verifying unique user IDs, ensuring no duplicate entries in a dataset, or implementing constraint checks, Python provides several efficient ways to solve this problem.

In this guide, you will learn multiple methods to check for uniqueness in a Python list, from the most efficient one-liner to manual approaches, with clear explanations of when to use each.

The most Pythonic and efficient way to check for uniqueness leverages the fact that sets automatically discard duplicates. If converting a list to a set preserves its length, all elements are unique.

a = [1, 2, 3, 4, 5]

is_unique = len(a) == len(set(a))

print(is_unique)

Output:

True

With duplicates:

b = [1, 2, 3, 2, 5]

is_unique = len(b) == len(set(b))

print(is_unique)

Output:

False

How it works:

  • set(a) creates a set from the list, automatically removing any duplicates.
  • If len(a) == len(set(a)), no elements were removed, meaning all elements are unique.
tip

This is the recommended approach for most situations. It runs in O(n) time and is the most concise solution. It works with any hashable elements (numbers, strings, tuples, etc.).

Using a Loop with a Set (Early Exit)​

While the set() comparison approach is clean, it always processes the entire list even if a duplicate is found at the very beginning. If you need to detect duplicates as early as possible (especially useful for very large lists) use a loop with a tracking set:

def all_unique(lst):
"""Check if all elements are unique, with early exit on first duplicate."""
seen = set()
for item in lst:
if item in seen:
return False
seen.add(item)
return True

# Test with unique elements
print(all_unique([1, 2, 3, 4, 5]))

# Test with a duplicate near the start
print(all_unique([1, 2, 1, 4, 5]))

Output:

True
False

How it works:

  • A seen set tracks elements encountered so far.
  • For each element, if it already exists in seen, a duplicate is found and the function returns False immediately.
  • If the loop completes without finding duplicates, all elements are unique.
info

This approach has the same O(n) worst-case time complexity as the set() method, but performs better in the average case when duplicates exist early in the list, because it exits as soon as the first duplicate is found.

Using collections.Counter​

The Counter class counts occurrences of each element. If every element appears exactly once, the list is unique.

from collections import Counter

a = [1, 2, 3, 4, 5]
counts = Counter(a)

is_unique = all(count == 1 for count in counts.values())

print(is_unique)

Output:

True

With duplicates:

b = [1, 2, 3, 2, 5]
counts = Counter(b)

is_unique = all(count == 1 for count in counts.values())

print(is_unique)

# You can also see which elements are duplicated
duplicates = [item for item, count in counts.items() if count > 1]
print(f"Duplicated elements: {duplicates}")

Output:

False
Duplicated elements: [2]

This method is more verbose than the set() approach but is useful when you also need to identify which elements are duplicated or how many times each appears.

Using max() on Counter Values​

A concise variation using Counter checks whether the maximum count across all elements is 1:

from collections import Counter

a = [1, 2, 3, 4, 5]

is_unique = max(Counter(a).values()) == 1

print(is_unique)

Output:

True
caution

This approach fails on empty lists because max() raises a ValueError when called on an empty sequence:

from collections import Counter

empty = []
# This raises: ValueError: max() arg is an empty sequence
is_unique = max(Counter(empty).values()) == 1

Output:

ValueError: max() iterable argument is empty

Fix: handle the empty case:

from collections import Counter

empty = []
counts = Counter(empty)
is_unique = max(counts.values(), default=1) == 1

print(is_unique) # True (empty list has no duplicates)

Using Nested Loops (Brute Force)​

This approach compares every element with every other element. It does not require extra space (beyond the result) but is significantly slower.

a = [1, 2, 3, 4, 5]

is_unique = all(
a[i] != a[j]
for i in range(len(a))
for j in range(i + 1, len(a))
)

print(is_unique)

Output:

True
caution

This method has O(n²) time complexity, making it impractical for large lists. It should only be used when:

  • The list is very small.
  • You cannot use extra memory for a set.
  • Elements are not hashable (though this is rare for standard Python types).

For a list of 10,000 elements, this approach makes ~50 million comparisons, while the set() method makes ~10,000 operations.

Handling Unhashable Elements​

The set() approach requires elements to be hashable (e.g., numbers, strings, tuples). If your list contains unhashable types like dictionaries or lists, you need an alternative approach.

Problem: sets cannot contain unhashable types:

a = [{"name": "Alice"}, {"name": "Bob"}, {"name": "Alice"}]

# This raises: TypeError: unhashable type: 'dict'
is_unique = len(a) == len(set(a))
# TypeError: unhashable type: 'dict'

Solution: use a comparison-based approach:

import json

a = [{"name": "Alice"}, {"name": "Bob"}, {"name": "Alice"}]

# Convert to a hashable representation
hashable = [json.dumps(item, sort_keys=True) for item in a]
is_unique = len(hashable) == len(set(hashable))

print(is_unique) # Output: False

Alternatively, for simple lists of lists:

a = [[1, 2], [3, 4], [1, 2]]

# Convert inner lists to tuples (which are hashable)
is_unique = len(a) == len(set(tuple(x) for x in a))

print(is_unique) # Output: False

Performance Comparison​

MethodTime ComplexitySpace ComplexityEarly ExitBest For
len(set()) comparisonO(n)O(n)āŒ NoGeneral use (recommended)
Loop with tracking setO(n)O(n)āœ… YesLarge lists, duplicates likely early
CounterO(n)O(n)āŒ NoWhen you also need duplicate details
Nested loopsO(n²)O(1)āœ… YesVery small lists, no extra memory
import timeit

a = list(range(100000)) # 100k unique elements

# Benchmark set comparison
t1 = timeit.timeit(lambda: len(a) == len(set(a)), number=100)

# Benchmark loop with set
def loop_check(lst):
seen = set()
for item in lst:
if item in seen:
return False
seen.add(item)
return True

t2 = timeit.timeit(lambda: loop_check(a), number=100)

print(f"set() comparison: {t1:.4f}s")
print(f"Loop with set: {t2:.4f}s")

Output (approximate):

set() comparison: 0.2069s
Loop with set: 0.5503s
info

For fully unique lists, the set() comparison is faster because set construction is optimized in C. The loop-based method is faster only when duplicates exist early in the list, allowing it to exit before processing all elements.

Summary​

Python provides several ways to check if a list contains all unique elements:

  • len(list) == len(set(list)): the simplest and fastest approach for most cases. Use this as your default.
  • Loop with a tracking set: best when you need early exit on large lists where duplicates are likely near the beginning.
  • collections.Counter: useful when you also need to know which elements are duplicated and how many times.
  • Nested loops: brute force, O(n²), only for very small lists or when extra memory is not available.

For the vast majority of use cases, the one-liner len(a) == len(set(a)) is the right choice because it's concise, efficient, and immediately readable.