Skip to main content

How to Convert a List into an Ordered Set in Python

A regular Python set removes duplicates but does not preserve order, so elements may appear in any arrangement. An ordered set removes duplicates while keeping the elements in the order they first appeared, which is essential when the sequence of your data matters.

For example, converting [3, 1, 4, 1, 5, 9, 2, 6, 5, 3] into an ordered set should produce [3, 1, 4, 5, 9, 2, 6], where duplicates are removed and the original order is maintained.

In this guide, you will learn multiple ways to convert a list into an ordered set in Python, from the most Pythonic built-in approaches to third-party libraries designed for set operations.

Since Python 3.7+, dictionaries guarantee insertion order. The dict.fromkeys() method creates a dictionary with list elements as keys, automatically discarding duplicates because dictionary keys must be unique. Converting the result back to a list gives you an ordered set:

original = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

ordered_set = list(dict.fromkeys(original))

print(ordered_set)

Output:

[3, 1, 4, 5, 9, 2, 6]

How it works:

  1. dict.fromkeys(original) creates {3: None, 1: None, 4: None, 5: None, 9: None, 2: None, 6: None}
  2. Duplicate keys (1, 5, 3) are silently ignored since dictionary keys must be unique
  3. list() converts the dictionary keys back to a list, preserving insertion order
tip

This is the most Pythonic and efficient approach for Python 3.7+. It is concise, requires no imports, and runs in O(n) time complexity.

Using OrderedDict.fromkeys()

For compatibility with Python 3.6 and earlier, where regular dictionaries did not guarantee insertion order, use OrderedDict from the collections module:

from collections import OrderedDict

original = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

ordered_set = list(OrderedDict.fromkeys(original))

print(ordered_set)

Output:

[3, 1, 4, 5, 9, 2, 6]

This works identically to dict.fromkeys() but explicitly guarantees order across all Python 3.x versions.

Using a Loop with a Tracking Set

A manual approach using a for loop gives you full control over the deduplication process. This is especially useful when you need custom logic, such as case-insensitive comparison or conditional filtering:

original = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

result = []
seen = set()

for item in original:
if item not in seen:
result.append(item)
seen.add(item)

print(result)

Output:

[3, 1, 4, 5, 9, 2, 6]

How it works:

  1. The seen set tracks which elements have already been encountered, with O(1) lookup time
  2. For each element, if it has not been seen before, it is added to both result and seen
  3. Duplicates are skipped because they are already present in seen

Custom Deduplication Logic

The loop approach allows you to define custom uniqueness criteria that go beyond simple equality:

# Case-insensitive deduplication
words = ['Apple', 'banana', 'apple', 'Cherry', 'BANANA', 'cherry']

result = []
seen = set()

for word in words:
key = word.lower()
if key not in seen:
result.append(word)
seen.add(key)

print(result)

Output:

['Apple', 'banana', 'Cherry']

Only the first occurrence of each word (compared case-insensitively) is kept in the result.

Why Not Use set() Directly?

A common mistake is converting to set and back to list, expecting the order to be preserved. However, set() does not guarantee any particular order:

original = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

unordered = list(set(original))
print(unordered)

Output (order may vary between runs):

[1, 2, 3, 4, 5, 6, 9]
warning

set() removes duplicates but rearranges elements in an arbitrary order determined by internal hash values. If the order of elements matters in your application, never rely on set() alone.

Using the ordered-set Library

For applications that need a true set-like object with order preservation, including full support for set operations like union, intersection, and difference, install the ordered-set package:

pip install ordered-set
from ordered_set import OrderedSet

original = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

os = OrderedSet(original)

print(os)
print(list(os))

Output:

OrderedSet([3, 1, 4, 5, 9, 2, 6])
[3, 1, 4, 5, 9, 2, 6]

Set Operations with Preserved Order

Unlike the dict.fromkeys() approach, OrderedSet supports standard set operations while maintaining element order:

from ordered_set import OrderedSet

a = OrderedSet([1, 2, 3, 4, 5])
b = OrderedSet([4, 5, 6, 7, 8])

print(f"Union: {a | b}")
print(f"Intersection: {a & b}")
print(f"Difference: {a - b}")

Output:

Union:        OrderedSet([1, 2, 3, 4, 5, 6, 7, 8])
Intersection: OrderedSet([4, 5])
Difference: OrderedSet([1, 2, 3])
note

This is the ideal choice when you need both order preservation and the full range of set operations.

Using List Comprehension with a Helper Set

A compact one-liner alternative uses a list comprehension with a side effect to track seen elements:

original = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

seen = set()
ordered_set = [x for x in original if x not in seen and not seen.add(x)]

print(ordered_set)

Output:

[3, 1, 4, 5, 9, 2, 6]
note

This works because seen.add(x) returns None (which is falsy), so not seen.add(x) is always True. The element is added to seen as a side effect during the condition check. While this is a clever trick, the explicit loop approach is generally clearer and more maintainable for production code.

Performance Comparison

import timeit
from collections import OrderedDict

data = list(range(1000)) * 10 # 10,000 items with many duplicates

# dict.fromkeys()
t1 = timeit.timeit(lambda: list(dict.fromkeys(data)), number=1000)

# OrderedDict.fromkeys()
t2 = timeit.timeit(lambda: list(OrderedDict.fromkeys(data)), number=1000)

# Loop with tracking set
def loop_method(lst):
result, seen = [], set()
for x in lst:
if x not in seen:
result.append(x)
seen.add(x)
return result

t3 = timeit.timeit(lambda: loop_method(data), number=1000)

print(f"dict.fromkeys(): {t1:.4f}s")
print(f"OrderedDict.fromkeys(): {t2:.4f}s")
print(f"Loop with set: {t3:.4f}s")

Typical output:

dict.fromkeys():        0.2153s
OrderedDict.fromkeys(): 0.3974s
Loop with set: 0.3812s
note

dict.fromkeys() is consistently the fastest because the entire operation is handled at the C level inside Python's dictionary implementation.

Quick Comparison of Methods

MethodPreserves OrderTime ComplexityRequires ImportBest For
dict.fromkeys()YesO(n)NoGeneral use (Python 3.7+)
OrderedDict.fromkeys()YesO(n)collectionsPython 3.6 compatibility
Loop with tracking setYesO(n)NoCustom deduplication logic
set()NoO(n)NoOnly when order does not matter
ordered-set libraryYesO(n)ordered-setSet operations with preserved order

Conclusion

Converting a list to an ordered set in Python is straightforward with several approaches available:

  • dict.fromkeys() is the fastest and most Pythonic option for Python 3.7+. It is a clean one-liner that requires no imports and handles the vast majority of use cases.
  • OrderedDict.fromkeys() provides the same functionality with guaranteed compatibility across all Python 3.x versions.
  • A loop with a tracking set gives you full control for custom deduplication logic, such as case-insensitive matching or conditional filtering.
  • The ordered-set library is the right choice when you need a proper set object that supports union, intersection, and difference operations while preserving element order.

For most everyday use cases, list(dict.fromkeys(your_list)) is all you need.