W3docs

Удаление дубликатов в Python: подробное руководство

Пять способов удаления дубликатов из списка Python: set, dict.fromkeys, цикл со множеством, списковое включение и Counter.

Дублирующиеся значения в списке Python встречаются повсеместно: при сборе пользовательского ввода, объединении наборов данных или чтении файлов. В этом руководстве рассматриваются пять практических способов удаления дубликатов — каждый с разным балансом между скоростью, сохранением порядка и читаемостью кода.

МетодСохраняет порядокРаботает с нехэшируемыми элементамиЧитаемость
set()НетНетВысокая
dict.fromkeys()Да (Python 3.7+)НетВысокая
Цикл со множеством seenДаНетСредняя
Списковое включениеДаНетСредняя
Counter (поиск дубликатов)ДаНетВысокая

Использование set() для удаления дубликатов

Преобразование списка в множество — самый быстрый и лаконичный способ устранить дубликаты. Множество хранит только уникальные хэшируемые значения, поэтому все повторяющиеся элементы автоматически отбрасываются.

python— editable, runs on the server

Вывод (порядок может отличаться):

[1, 2, 3, 4, 5]

Когда использовать: порядок элементов не важен, и список содержит только хэшируемые элементы (числа, строки, кортежи).

Предупреждение: множества неупорядочены. Даже если небольшие множества целых чисел часто выводятся в отсортированном порядке, полагаться на это нельзя. Если порядок важен, используйте один из методов ниже.

Использование dict.fromkeys() для сохранения порядка

dict.fromkeys() создаёт словарь, ключами которого являются элементы списка. Поскольку ключи словаря уникальны и, начиная с Python 3.7, сохраняют порядок вставки, этот метод удаляет дубликаты, сохраняя исходный порядок.

python— editable, runs on the server

Вывод:

[1, 2, 3, 4, 5]

Это идиоматическая однострочная конструкция для дедупликации с сохранением порядка в современном Python (3.7+). Она также немного быстрее явного цикла, поскольку операции со словарём выполняются на уровне C.

Использование цикла for с множеством seen

Когда требуется полный контроль — например, чтобы логировать пропущенные дубликаты или применять пользовательскую логику сравнения, — явный цикл является наиболее понятным подходом.

def remove_duplicates(lst):
    seen = set()
    result = []
    for item in lst:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result

my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
print(remove_duplicates(my_list))

Вывод:

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

Этот подход сохраняет порядок вставки и работает за O(n) — проверка in для множества выполняется за O(1). Сравните с проверкой if item not in result, которая занимает O(n) для каждого элемента и делает функцию O(n²) в целом.

Использование спискового включения

Тот же паттерн с множеством seen можно записать в одну строку с помощью спискового включения. Трюк состоит в том, что set.add() всегда возвращает None (ложное значение), поэтому выражение not (x in seen or seen.add(x)) равно True только при первом появлении каждого значения.

my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
seen = set()
unique = [x for x in my_list if not (x in seen or seen.add(x))]
print(unique)

Вывод:

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

Такая запись компактна, но опирается на побочный эффект внутри включения, что может удивить читателя. Явный цикл выше зачастую предпочтительнее в командном коде.

Использование Counter для поиска дублирующихся значений

Иногда нужно знать, какие значения встречаются более одного раза, а не просто удалить их. collections.Counter подсчитывает вхождения и упрощает эту задачу.

from collections import Counter

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

duplicates = [item for item, count in counts.items() if count > 1]
print("Duplicated values:", duplicates)

Вывод:

Counter({5: 3, 2: 2, 4: 2, 1: 1, 3: 1})
Duplicated values: [2, 4, 5]

Чтобы получить дедуплицированный список из Counter, используйте list(counts.keys()) — ключи сохраняют порядок вставки в Python 3.7+.

Удаление дубликатов из DataFrame с помощью Pandas

Если вы работаете с табличными данными, библиотека Pandas предоставляет DataFrame.drop_duplicates(). Метод поддерживает точную настройку через параметры.

import pandas as pd

data = {
    'name': ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob'],
    'score': [90, 85, 90, 78, 85],
}
df = pd.DataFrame(data)
df_unique = df.drop_duplicates()
print(df_unique)

Вывод:

      name  score
0    Alice     90
1      Bob     85
3  Charlie     78

Ключевые параметры:

  • subset — имя столбца или список столбцов, по которым выполняется проверка. Дубликаты определяются только в рамках этих столбцов.
  • keep'first' (по умолчанию) сохраняет первое вхождение; 'last' — последнее; False удаляет все строки, имеющие дубликаты.
  • inplace=True — изменяет DataFrame на месте вместо возврата нового объекта.
# Keep only the last occurrence of each name
df_last = df.drop_duplicates(subset='name', keep='last')
print(df_last)

Вывод:

      name  score
2    Alice     90
3  Charlie     78
4      Bob     85

Выбор подходящего метода

  • Максимальная скорость, порядок не важенset().
  • Порядок важен, однострочное решениеdict.fromkeys().
  • Пользовательская логика или логирование — явный цикл for с множеством seen.
  • Табличные данныеpandas.DataFrame.drop_duplicates().
  • Нужно узнать, какие значения дублируютсяcollections.Counter.

Подробнее о работе со списками см. главу Python Lists и полный справочник методов списка. Чтобы узнать о множествах и операциях с ними, см. Python Sets и Set Methods.

Was this page helpful?