Python: как удалить дубликаты из списка и сохранить порядок
Самый короткий способ удалить дубликаты из списка в Python с сохранением порядка: list(dict.fromkeys(items)). Если порядок не важен, подойдёт list(set(items)). Для списков словарей нужна отдельная функция.
Быстрые варианты
items = [3, 1, 3, 2, 1, 5]
# 1. Сохраняет порядок первого появления (Python 3.7+)
unique = list(dict.fromkeys(items))
print(unique) # [3, 1, 2, 5]
# 2. Порядок не гарантирован
unique = list(set(items))
# 3. Отсортированный результат без повторов
unique = sorted(set(items))Способ с dict.fromkeys работает потому, что ключи словаря уникальны, а начиная с Python 3.7 словарь помнит порядок вставки.
Когда какой способ использовать
Задача | Решение | Порядок сохраняется |
|---|---|---|
Элементы хешируемые (числа, строки, кортежи) |
| Да |
Порядок не нужен, важна скорость |
| Нет |
Нужен отсортированный результат |
| По значению |
Элементы — списки или словари | Функция с | Да |
Дубликаты определяются по одному полю | Функция с ключом (ниже) | Да |
Дубликаты в списке словарей или списков
Списки и словари нельзя положить в set: они изменяемые, поэтому нехешируемые. Вместо этого запоминайте уже встреченные значения.
def unique_by(items, key=lambda x: x):
"""Удаляет дубликаты, сохраняя порядок первого появления."""
seen = set()
result = []
for item in items:
marker = key(item)
if marker not in seen:
seen.add(marker)
result.append(item)
return result
users = [
{"id": 1, "name": "Анна"},
{"id": 2, "name": "Борис"},
{"id": 1, "name": "Анна"},
]
# дубликаты определяем по полю id
print(unique_by(users, key=lambda u: u["id"]))
# [{'id': 1, 'name': 'Анна'}, {'id': 2, 'name': 'Борис'}]
# список списков: превращаем во вложенный кортеж
rows = [[1, 2], [3, 4], [1, 2]]
print(unique_by(rows, key=tuple)) # [[1, 2], [3, 4]]Удалить дубликаты на месте
Если список нужно изменить, а не создать новый, присвойте результат срезу:
items = [3, 1, 3, 2, 1, 5]
items[:] = dict.fromkeys(items)
print(items) # [3, 1, 2, 5]Без учёта регистра
Для строк используйте ключ str.casefold: в результате останется первое написание.
tags = ["Python", "python", "SQL", "sql", "Git"]
print(unique_by(tags, key=str.casefold)) # ['Python', 'SQL', 'Git']Частые вопросы
Почему list(set(items)) меняет порядок?
Множество (set) не хранит порядок элементов. Чтобы его сохранить, используйте dict.fromkeys.
Как найти повторяющиеся элементы, а не удалить их?
Посчитайте элементы через collections.Counter и оставьте те, что встречаются больше одного раза:
from collections import Counter
items = ["a", "b", "a", "c", "b"]
duplicates = [value for value, count in Counter(items).items() if count > 1]
print(duplicates) # ['a', 'b']Работает ли dict.fromkeys в старых версиях Python?
Порядок ключей гарантируется языком с версии 3.7. В CPython 3.6 он тоже сохраняется, но как деталь реализации.