Удаление повторяющихся элементов из списка в Python — частая задача, и есть несколько эффективных способов сделать это, каждый со своими особенностями (например, сохраняется ли порядок элементов).
1. Использование Set() (Наиболее распространенный и рекомендуемый способ, но без сохранения порядка)
Это самый простой, короткий и эффективный способ, если вам Неважен порядок элементов в исходном списке. Множества (set) в Python по определению не содержат дубликатов.
Python
Original_list = [1, 2, 2, 3, 4, 4, 5, 1, 6, 7, 7]
# 1. Преобразуем список в множество (дубликаты удаляются)
Unique_set = set(original_list)
Print(f"Множество уникальных элементов: {unique_set}") # Вывод: {1, 2, 3, 4, 5, 6, 7} (порядок не гарантирован)
# 2. Преобразуем множество обратно в список
Unique_list = list(unique_set)
Print(f"Список с уникальными значениями (порядок не сохранен): {unique_list}")
# Вывод: Список с уникальными значениями (порядок не сохранен): [1, 2, 3, 4, 5, 6, 7]
# (Порядок может отличаться при каждом запуске)
# Короткая запись:
Unique_list_short = list(set(original_list))
Print(f"Короткая запись: {unique_list_short}")
Плюсы:
- Простота и читабельность: Код очень лаконичен. Эффективность: Создание множества и добавление элементов в него очень быстрые (в среднем O(1) для каждой операции), что делает этот метод очень эффективным для больших списков.
Минусы:
- Потеря порядка: Множества по своей природе неупорядочены. Если исходный порядок элементов важен, этот метод его не сохранит. Требует хешируемых элементов: Все элементы в списке должны быть Хешируемыми (immutable, например, числа, строки, кортежи). Если список содержит изменяемые объекты (например, другие списки или словари), вы получите TypeError: unhashable type: ‘list’.
2. Сохранение порядка с использованием Set() и цикла
Если вам нужно сохранить исходный порядок элементов, но при этом удалить дубликаты, вы можете использовать комбинацию множества (для отслеживания уже добавленных элементов) и цикла.
Python
Original_list = [1, 2, 2, 3, 4, 4, 5, 1, 6, 7, 7]
Unique_list_ordered = []
Seen = set() # Множество для отслеживания уже увиденных элементов
For item in original_list:
if item not in seen: # Если элемент еще не был добавлен
unique_list_ordered. append(item)
seen. add(item)
Print(f"Список с уникальными значениями (с сохранением порядка): {unique_list_ordered}")
# Вывод: Список с уникальными значениями (с сохранением порядка): [1, 2, 3, 4, 5, 6, 7]
Плюсы:
- Сохраняет порядок: Элементы в результирующем списке будут находиться в том же порядке, в каком они впервые появились в исходном списке. Эффективность: Благодаря использованию set для seen проверка item not in seen происходит очень быстро (в среднем O(1)), что делает этот метод также очень эффективным.
Минусы:
- Требует хешируемых элементов: Как и в первом способе, элементы должны быть хешируемыми. Более многословен, чем простой list(set()).
3. Использование Dict. fromkeys() (Python 3.7+ для сохранения порядка)
Начиная с Python 3.7, словари сохраняют порядок вставки элементов. Это позволяет использовать dict. fromkeys() для удаления дубликатов, сохраняя порядок.
Python
Original_list = [1, 2, 2, 3, 4, 4, 5, 1, 6, 7, 7]
# Создаем словарь, где ключами становятся элементы списка.
# dict. fromkeys() принимает итерируемый объект и создает словарь,
# используя его элементы как ключи. Дублирующиеся ключи перезаписываются,
# оставляя только первое вхождение, но при этом сохраняется порядок.
Unique_list_dict_fromkeys = list(dict. fromkeys(original_list))
Print(f"Список с уникальными значениями (через dict. fromkeys): {unique_list_dict_fromkeys}")
# Вывод: Список с уникальными значениями (через dict. fromkeys): [1, 2, 3, 4, 5, 6, 7]
Плюсы:
- Краткий код. Сохраняет порядок (с Python 3.7+). Эффективен (почти так же, как set).
Минусы:
- Требует хешируемых элементов. Может быть менее очевиден для тех, кто не знает о поведении словарей с Python 3.7+.
4. Генератор списка с проверкой Not in (Не рекомендуется для больших списков)
Можно использовать генератор списка или простой цикл с проверкой item not in new_list для создания нового списка.
Python
Original_list = [1, 2, 2, 3, 4, 4, 5, 1, 6, 7, 7]
Unique_list_loop = []
For item in original_list:
if item not in unique_list_loop: # Проверка наличия
unique_list_loop. append(item)
Print(f"Список с уникальными значениями (цикл с in): {unique_list_loop}")
# Вывод: Список с уникальными значениями (цикл с in): [1, 2, 3, 4, 5, 6, 7]
Плюсы:
- Сохраняет порядок. Работает с Нехешируемыми элементами (например, списками внутри списка), хотя сравнение in для нехешируемых объектов может быть медленным.
Минусы:
- Низкая производительность: Проверка item not in unique_list_loop имеет сложность O(N) (линейное время) для каждого элемента в цикле. Это означает, что общая сложность алгоритма становится O(N2) (квадратичной), что очень медленно для больших списков. Избегайте этого для больших списков.
Выбор метода:
Если порядок элементов не важен: Используйте unique_list = list(set(original_list)). Это самый быстрый, простой и "питоновский" способ. Если порядок элементов важен и элементы хешируемы:
- С Python 3.7+: unique_list = list(dict. fromkeys(original_list)). Для более старых версий Python или если вы предпочитаете более явную логику: используйте цикл с множеством seen (второй метод).
Если элементы нехешируемы (например, списки внутри списка) и порядок важен: Вам придется использовать цикл с проверкой item not in new_list (четвертый метод). Однако, будьте готовы к тому, что это будет очень медленно для больших списков. В таких случаях, возможно, стоит пересмотреть структуру данных или найти более специализированные алгоритмы, если производительность критична.
Всегда старайтесь использовать set или dict. fromkeys() для уникализации, если это возможно, из-за их высокой эффективности.