Как сделать список уникальным (без повторяющихся элементов)python-71

1. Основные методы удаления дубликатов

1.1. Использование множества - простой способ

Самый быстрый способ, но не сохраняет порядок элементов:

original = [3, 1, 2, 2, 4, 3, 1]
unique = list(set(original))
print(unique)  # Может получиться [1, 2, 3, 4] (порядок не гарантирован)

1.2. Сохранение порядка с OrderedDict

Используем словарь для сохранения порядка:

from collections import OrderedDict

original = [3, 1, 2, 2, 4, 3, 1]
unique = list(OrderedDict.fromkeys(original))
print(unique)  # [3, 1, 2, 4] (порядок сохранен)

1.3. Через генератор списка с проверкой

Медленнее, но сохраняет порядок и понятен:

original = [3, 1, 2, 2, 4, 3, 1]
unique = []
[unique.append(x) for x in original if x not in unique]
print(unique)  # [3, 1, 2, 4]

2. Дополнительные методы

2.1. Использование dict.fromkeys

Простой способ с сохранением порядка:

original = [3, 1, 2, 2, 4, 3, 1]
unique = list(dict.fromkeys(original))
print(unique)  # [3, 1, 2, 4]

2.2. Фильтрация с помощью itertools.groupby

Полезно для отсортированных списков:

from itertools import groupby

original = [1, 1, 2, 2, 3, 4, 4]
unique = [k for k, _ in groupby(sorted(original))]
print(unique)  # [1, 2, 3, 4]

2.3. Использование pandas.unique

Для работы с большими данными:

import pandas as pd

original = [3, 1, 2, 2, 4, 3, 1]
unique = pd.unique(original).tolist()
print(unique)  # [3, 1, 2, 4] (порядок сохранен)

3. Сравнение производительности методов

Тестирование скорости:

from timeit import timeit

setup = "original = [3, 1, 2, 2, 4, 3, 1] * 1000"

methods = {
    "set": "list(set(original))",
    "OrderedDict": "list(OrderedDict.fromkeys(original))",
    "dict": "list(dict.fromkeys(original))",
    "list comp": "[x for i, x in enumerate(original) if x not in original[:i]]"
}

for name, code in methods.items():
    time = timeit(code, setup, number=1000, globals=globals())
    print(f"{name:10}: {time:.5f} sec")

Результаты (чем меньше время, тем лучше):

  • set: самый быстрый, но без сохранения порядка
  • dict/OrderedDict: немного медленнее, но сохраняют порядок
  • list comprehension: самый медленный для больших списков

4. Особые случаи

4.1. Уникальность для нехэшируемых элементов

Если элементы списка - словари или списки:

original = [{'a': 1}, {'b': 2}, {'a': 1}]

# Способ 1: через сравнение словарей
unique = []
for item in original:
    if item not in unique:
        unique.append(item)

# Способ 2: через сериализацию в строку
unique = [eval(x) for x in set([str(x) for x in original])]

4.2. Удаление дубликатов с условием

Например, оставить последнее вхождение:

original = [3, 1, 2, 2, 4, 3, 1]
unique = list({x: i for i, x in enumerate(original)}.keys())
print(unique)  # [2, 4, 3, 1]

Резюмируем

  1. Для простых случаев (нетребовательность к порядку):

    • list(set(original)) - самый быстрый способ
  2. С сохранением порядка:

    • list(dict.fromkeys(original)) (Python 3.7+)
    • list(OrderedDict.fromkeys(original)) (все версии Python)
  3. Для сложных объектов:

    • Ручная проверка через not in
    • Сериализация в строку
  4. Для больших данных:

    • pandas.unique() может быть эффективнее

Выбор метода зависит от:

  • Требований к порядку элементов
  • Размера списка
  • Типа элементов списка
  • Версии Python