Python
Duplicate Detection
Data Structures
Algorithms
Programming

Python find a duplicate in a container efficiently

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Duplicate detection in Python depends on what result you need, not only on big-O complexity. Some workflows only need a boolean answer, others need the first duplicate in order, and others need full frequency counts. Efficient solutions are usually set-based, but edge cases such as unhashable values and stream limits change the implementation.

Core Sections

1. Fast existence check with set length

If you only need to know whether duplicates exist, compare input length with set length.

python
1def has_duplicates(items):
2    return len(items) != len(set(items))
3
4print(has_duplicates([1, 2, 3, 2]))  # True
5print(has_duplicates([1, 2, 3]))     # False

This is average linear time with memory proportional to distinct values.

2. Find first duplicate by encounter order

For logs and streams, first repeated item order often matters.

python
1def first_duplicate(items):
2    seen = set()
3    for x in items:
4        if x in seen:
5            return x
6        seen.add(x)
7    return None
8
9print(first_duplicate([4, 1, 3, 1, 2]))  # 1

This keeps order semantics while staying efficient.

3. Count all repeated values with Counter

When you need frequency reports, collections.Counter is the right tool.

python
1from collections import Counter
2
3items = ["a", "b", "a", "c", "b", "b"]
4counts = Counter(items)
5duplicates = {k: v for k, v in counts.items() if v > 1}
6print(duplicates)  # {'a': 2, 'b': 3}

This gives richer output for audits and data quality checks.

4. Memory-aware sorted approach

If hash-set growth is a concern and order is irrelevant, sort then compare neighbors.

python
1def has_duplicates_sorted(items):
2    data = sorted(items)
3    for i in range(1, len(data)):
4        if data[i] == data[i - 1]:
5            return True
6    return False
7
8print(has_duplicates_sorted([9, 5, 1, 9]))  # True

Time becomes n log n, but this can be acceptable when memory constraints dominate.

5. Unhashable containers need canonical forms

Lists and dicts cannot go directly into sets. Convert them into hashable representations.

python
1import json
2
3records = [
4    {"id": 1, "name": "a"},
5    {"name": "a", "id": 1},
6    {"id": 2, "name": "b"},
7]
8
9keys = [json.dumps(r, sort_keys=True) for r in records]
10print(len(keys) != len(set(keys)))  # True

Canonicalization rules should match business semantics.

6. Stream-oriented duplicate detection

For long or unbounded streams, keep incremental state and emit duplicates as they appear.

python
1def stream_duplicates(stream):
2    seen = set()
3    for value in stream:
4        if value in seen:
5            yield value
6        else:
7            seen.add(value)
8
9for d in stream_duplicates([1, 2, 3, 2, 4, 1, 5, 1]):
10    print(d)

For very large streams, you may need windowing or external state stores.

7. Case and normalization rules

Text duplicate checks often fail due to case and whitespace differences. Normalize before comparison when needed.

python
1def normalized_duplicates(strings):
2    cleaned = [s.strip().lower() for s in strings]
3    return len(cleaned) != len(set(cleaned))
4
5print(normalized_duplicates([" Apple", "apple", "Banana"]))

Define normalization policy explicitly to avoid surprising results.

8. Choosing algorithm by requirement

Use this quick decision guide:

  • need boolean only: set-length check
  • need first duplicate by order: seen-set scan
  • need count report: Counter
  • memory constrained and order irrelevant: sort-and-scan

Choosing by output requirement prevents overengineering.

9. Testing and correctness checks

Duplicate logic is easy to misread when requirements evolve. Include tests for:

  • empty input
  • no duplicates
  • repeated duplicates
  • mixed types
  • normalized text behavior

Explicit tests make future refactors safe.

Common Pitfalls

  • Using quadratic nested loops on large inputs.
  • Forgetting unhashable values cannot be inserted into sets.
  • Ignoring normalization for semantically equivalent text values.
  • Choosing sort-based method when order-dependent output is required.
  • Treating probabilistic duplicate methods as exact without documentation.

Summary

  • Efficient duplicate detection in Python is usually set-based.
  • Different tasks require different outputs and data structures.
  • Counter is best for frequency, seen-set scan is best for first duplicate order.
  • Normalize and canonicalize inputs when semantic equivalence matters.
  • Pick algorithm by requirement, then validate with targeted tests.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.