How do I remove duplicates from a list, while preserving order?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Removing duplicates while keeping the first occurrence order is a common data-cleaning task in Python. The best solution depends on your Python version and on whether the list items are hashable, but for most modern code the simplest answer is dict.fromkeys.
Use dict.fromkeys in Modern Python
Since modern Python dictionaries preserve insertion order, you can build a dictionary from the list values and turn the keys back into a list.
This keeps the first occurrence of each value and removes later duplicates. It is concise, idiomatic, and usually the cleanest choice in Python 3.7 and later.
Use a Set and a Loop When You Need More Control
The explicit loop is slightly longer, but it lets you combine de-duplication with other logic.
This is a good pattern when you want to validate, transform, or log values while preserving order.
Handle Older Python Versions with OrderedDict
If you are maintaining older Python where regular dictionaries do not guarantee insertion order, use collections.OrderedDict.
This is mostly a compatibility technique now, but it is still worth knowing for legacy codebases.
Unhashable Items Need a Different Approach
The fast approaches rely on hash-based membership checks, so they do not work directly for unhashable values such as lists or dictionaries. In that case, use a manual loop and compare values directly.
This preserves order, but it is slower because each membership check scans the result list.
Use a Key Function for Normalized Uniqueness
Sometimes uniqueness is based on a normalized version of the value, such as lowercase email addresses or trimmed strings. In that case, track the normalized key but keep the original value.
That pattern is often more useful in real data pipelines than exact-value de-duplication.
Think About What Duplicate Means
Order-preserving de-duplication always keeps one representative value. Usually that is the first occurrence, but not always. If the business rule says the last value should win, you need a different implementation. The code should reflect that rule explicitly instead of assuming that any de-duplication behavior is acceptable.
Common Pitfalls
- Using a plain
setdirectly and losing the original order of the list. - Assuming
dict.fromkeysworks for every item type, even when elements are unhashable. - Forgetting that de-duplication usually keeps the first occurrence, not the last one.
- Comparing raw values when the real uniqueness rule should be case-insensitive or normalized.
- Optimizing for brevity and hiding important business rules about which value should be preserved.
Summary
- Use
list(dict.fromkeys(items))as the default modern Python solution. - Use a loop with a
seenset when you need extra processing or clarity. - Use
OrderedDict.fromkeysonly for older Python compatibility. - Fall back to list-based checking for unhashable items.
- Make the uniqueness rule explicit when normalized or business-specific matching is required.
Related reading
- How do I reverse a list or loop over it backwards?
- How do I search for a number in a 2d array sorted left to right and top to bottom?
- How do I sort a dictionary by key?
- How do I sort a dictionary by key?
- How do I remove duplicates from a list, while preserving order?
- How do I remove local untracked files from the current Git working tree?
- How do I remove leading whitespace in Python?
- How do I remove NaN values from a NumPy array?

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 courseTrack 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.