Найти в Дзене
PythonTalk

5 способов удалить дубликаты из списка в Python: от дедовского цикла до трюка для профи

Удаление дубликатов из списка — это как «Hello, World!» на собеседованиях. Задача, которую задают каждому второму джуну, и на которой умудряются посыпаться даже ребята с опытом. Кажется, что может быть проще? Но за этой простотой скрывается целая священная война методов, у каждого из которых есть свои фанаты и хейтеры. Давай разберемся раз и навсегда, какой способ для чего годится, а какой лучше вообще не показывать приличному сеньору. Это первое, что приходит в голову. И, будем честны, в 80% случаев этого достаточно. Превратил список в множество, потом обратно в список — профит! Это первое, чт приходит в голову многим. И правда, что может быть проще? Превратил список в set — и все дубликаты исчезли. Что под капотом? Множества по своей природе не могут содержать дубликатов. Быстро, лаконично, в одну строчку. В чём подвох? Порядок элементов летит к чертям. Если тебе было важно, чтобы 1 шла перед 5, а 5 перед 6 — можешь попрощаться с этой идеей. set не гарантирует вообще ничего. Идеально
Оглавление

Удаление дубликатов из списка — это как «Hello, World!» на собеседованиях. Задача, которую задают каждому второму джуну, и на которой умудряются посыпаться даже ребята с опытом. Кажется, что может быть проще? Но за этой простотой скрывается целая священная война методов, у каждого из которых есть свои фанаты и хейтеры.

Давай разберемся раз и навсегда, какой способ для чего годится, а какой лучше вообще не показывать приличному сеньору.

1. Метод очевидный: set() 🧐

Это первое, что приходит в голову. И, будем честны, в 80% случаев этого достаточно. Превратил список в множество, потом обратно в список — профит!

Это первое, чт приходит в голову многим. И правда, что может быть проще? Превратил список в set — и все дубликаты исчезли.

-2

Что под капотом? Множества по своей природе не могут содержать дубликатов. Быстро, лаконично, в одну строчку.

В чём подвох? Порядок элементов летит к чертям. Если тебе было важно, чтобы 1 шла перед 5, а 5 перед 6 — можешь попрощаться с этой идеей. set не гарантирует вообще ничего. Идеально, если тебе на порядок было плевать с самого начала.

2. Метод дедовский: цикл for 👨🏻‍💻

Классика. Дедовский способ. Создаем новый пустой список и добавляем в него элементы, только если их там еще нет.

-3

Что под капотом? Честная, прямолинейная работа. Код понятен даже тому, кто открыл учебник по Python вчера. И главное — порядок сохраняется!

В чём подвох? Производительность. На каждой итерации ты используешь if i not in new_list, что само по себе запускает внутренний цикл поиска. На больших списках это будет работать медленнее, чем тащить рояль на 9 этаж без лифта. Для списка из 10 элементов — ок. Для 10 миллионов — ты рискуешь уйти на обед и вернуться к всё еще работающему скрипту.

3. Метод дата-сатаниста: библиотека NumPy 🤖

Если ты уже погряз в данных и import numpy as np для тебя как утренняя молитва, то этот способ для тебя.

-4

Что под капотом? Мощные, оптимизированные на C алгоритмы NumPy. Скорее всего, это будет очень быстро.

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

4. Трюк для посвящённых: dict.fromkeys() 🧠

А вот это уже интересно. Этот способ выглядит как магия, но под капотом у него простая и гениальная логика.

-5

Что под капотом? Мы создаем словарь, используя элементы списка в качестве ключей. Ключи в словаре, как и элементы в множестве, уникальны. Но, начиная с Python 3.7, словари сохраняют порядок вставки ключей. Превращая ключи этого словаря обратно в список, мы получаем то, что хотели: уникальные элементы с сохранением исходного порядка.

В чём подвох? Да почти ни в чем. Это быстро, это элегантно, это не требует импортов. Единственный минус — это может быть не так очевидно для новичка. Но мы же тут за эффективность, а не за детский сад, верно?

5. Метод из внешнего мира: more-itertools 📦

Для тех, кто не хочет изобретать велосипед и любит хорошие инструменты.

-6

Что под капотом? more-itertools — это крутая библиотека с кучей утилит для работы с итерируемыми объектами. Функция unique_everseen делает именно то, что нужно: возвращает уникальные элементы, сохраняя порядок их первого появления.

В чём подвох? Тот же, что и с NumPy — внешняя зависимость. Да, она не такая тяжелая, но все же это лишняя строчка в requirements.txt. Стоит ли оно того, когда есть трюк с dict.fromkeys()? Решать тебе.

Так что в итоге? 🔥

  • Если тебе плевать на порядок, бери set(). Быстро и сердито.
  • Если пишешь учебный проект и хочешь понятный код, пиши цикл for. Но не показывай это на работе.
  • Если у тебя в проекте уже есть NumPy, используй np.unique().
  • Но если ты хочешь сделать как надо — быстро, элегантно, без лишних зависимостей и с сохранением порядка — твой выбор это list(dict.fromkeys(my_list)).

Это и есть тот самый баланс, который отличает опытного разработчика от новичка, который лепит set() везде, где надо и не надо.

Больше таких разборов в моем телеграм-канале PythonTalk. Подписывайся!