Рубрики
Без рубрики

Список Python: удалите дубликаты и сохраняйте заказ

Удаление дубликатов из списка довольно прост. Вы можете сделать это с помощью Python One-LiLer: >>> Первоначально = [1, 1, 9, 1, 9, 6, 9, 7] >>> (набор (начальный)) >>> Результат [1, 7 , 9, 6] Установленные элементы Python должны быть уникальными, поэтому преобразование списка в набор и обратно после достижения … Python List: Удалить дубликаты и держать заказ Подробнее »

Автор оригинала: Jonathan Boland.

Удаление дубликатов из списка довольно прост. Вы можете сделать это с помощью одноклассника Python:

>>> initial = [1, 1, 9, 1, 9, 6, 9, 7]
>>> result = list(set(initial))
>>> result
[1, 7, 9, 6]

Установленные элементы Python должны быть уникальными, поэтому преобразование списка в набор и снова достигает желаемого результата.

Что если оригинальный порядок списка важен, хотя? Это делает вещи немного сложнее, потому что наборы неупорядочены, поэтому, как только вы закончите преобразование, порядок списка будет потерян.

К счастью, есть несколько способов преодоления этого вопроса. В этой статье мы рассмотрим ряд различных решений проблемы и рассмотрим их относительные достоинства.

Метод 1 – для цикла

Базовый способ добиться необходимого результата – с циклом для цикла:

 >>> initial = [1, 1, 9, 1, 9, 6, 9, 7]
 >>> result = []
 >>> for item in initial:
         if item not in result:
             result.append(item)
 >>> result
 
 [1, 9, 6, 7]

Этот подход, по крайней мере, имеет преимущество в том, что его легко прочитать и понять. Это довольно неэффективно, хотя и Не я n Проверка завершена для каждого элемента Первоначальный Список Отказ

Это может не быть проблемой с этим простым примером, но время накладных расходов станет все более очевидным, если список станет очень большим.

Метод 2 – Понимание списка

Одна альтернатива – использовать список пониманий:

 >>> initial = [1, 1, 9, 1, 9, 6, 9, 7]
 >>> result = []
 >>> [result.append(item) for item in initial if item not in result]
 [None, None, None, None]
 >>> result
 
 [1, 9, 6, 7]

Сопроизведения списка удобны и очень мощные инструменты Python, которые позволяют объединять переменные, для петлей и если выступления. Они позволяют создать список с одной строкой кода (но вы можете разделить их на несколько строк, чтобы улучшить удобочитаемость!).

Хотя короче и до сих пор довольно четко с использованием понимания списка в этом случае не очень хорошая идея.

Это потому, что это требует того же неэффективного подхода к тестированию членства, которое мы видели в Метод 1 Отказ Это также опирается на побочные эффекты понимания для создания списка результатов, которые многие считают плохие практики.

Чтобы объяснить дальше, даже если он не назначен переменной для более позднего использования, понимание списка по-прежнему создает объект списка. Итак, в процессе Приобретая предметы из исходного списка к Результат Список наш код также создает третий список, содержащий возвращаемое значение каждого Результат. Append (товар) вызов.

Функции Python возвращают значение Нет Если другое возвращаемое значение не указано, что означает, что (как вы можете видеть выше) Выход из третьего списка:

[None, None, None, None]

A для петли яснее и не полагается на побочные эффекты, так что является лучшим методом двух по этому поводу.

Метод 3 – Сортированный набор

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

 >>> initial = [1, 1, 9, 1, 9, 6, 9, 7]
 >>> result = sorted(set(initial), key=initial.index)
 >>> result
 
 [1, 9, 6, 7]

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

Проблема в том, что хотя она довольно легко понять, что это не намного быстрее, чем основной для цикла, показанного в Метод 1 Отказ

Метод 4 – Словарь Pleteys ()

Серьезно быстрый подход – использовать словарь:

 >>> initial = [1, 1, 9, 1, 9, 6, 9, 7]
 >>> result = list(dict.fromkeys(initial))
 >>> result
 
 [1, 9, 6, 7]

Как и наборы, словари используют хэш-таблицы, что означает, что они чрезвычайно быстрые.

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

Dict.Fromkeys () Способ создает новый словарь, используя элементы из итерапы, как клавиши.

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

Словари стало только приказано только во всех реализациях Python, когда был выпущен Python 3.7 (это также была деталь реализации CPYPHON 3.6).

Итак, если вы используете старую версию Python, вам нужно будет импортировать ЗаказДикт Класс из пакета коллекций в стандартной библиотеке вместо этого:

 >>> from collections import OrderedDict
 >>> initial = [1, 1, 9, 1, 9, 6, 9, 7]
 >>> result = list(OrderedDict.fromkeys(initial))
 >>> result
 
 [1, 9, 6, 7]

Этот подход не может быть не так быстро, как и использует стандартный словарь, но это все еще очень быстро!

Упражнение: Запустите код. Это работает?

Метод 5 – больше-iTertools

До этого момента мы только смотрели на списки, содержащие неизменные предметы Отказ Но что, если ваш список содержит смежные типы данных, такие как списки, наборы или словари?

Еще можно использовать базовый для петли, показанный в Метод 1 , но это не сократит горчицу, если скорость имеет сущность.

Кроме того, если мы попытаемся использовать Dict.Fromkeys () Мы получим Типеррор Потому что ключей словаря должны быть хмаристыми.

Отличный ответ на эту загадку поставляется в форме библиотеки, называемой More-Itertools Отказ Это не часть стандартной библиотеки Python, поэтому вам нужно PIP Установить это Отказ

С помощью этого вы можете импортировать и использовать его Unique_everseen () Функция такая:

 >>> from more_itertools import unique_everseen
 >>> mutables = [[1, 2, 3], [2, 3, 4], [1, 2, 3]]
 >>> result = list(unique_everseen(mutables))
 >>> result
 
 [[1, 2, 3], [2, 3, 4]]

Библиотека More-Itertools Разработан специально для работы с утеряемыми типами данных Python в эффективных способах (он дополняет Itertools, которая является частью стандартной библиотеки).

Функция Unique_everseen () дает уникальные элементы при сохранении порядка и важно, он может обрабатывать смежные типы данных, так что именно то, что мы ищем.

Функция также обеспечивает способ удаления дубликатов еще быстрее из списка списков:

 ...
 >>> result = list(unique_everseen(mutables, key=tuple))
 >>> result
 
 [[1, 2, 3], [2, 3, 4]]

Это хорошо работает, потому что он преобразует несчастье в хэш-кортежи, чтобы ускорить вещи дальше.

Если вы хотите применить этот трюк в список наборов, вы можете использовать Frozenset Как ключ:

 ...
 >>> mutables = [{1, 2, 3}, {2, 3, 4}, {1, 2, 3}]
 >>> result = list(unique_everseen(mutables, key=frozenset))
 >>> result
 
 [{1, 2, 3}, {2, 3, 4}]

Указание ключа со списком словарей – это немного сложнее, но все еще может быть достигнуто с помощью функции Lambda:

 ...
 >>> mutables = [{'one': 1}, {'two': 2}, {'one': 1}]
 >>> result = list(
     unique_everseen(mutables, key=lambda x: frozenset(x.items()))
     )
 >>> result
 
 [{'one': 1}, {'two': 2}]

Функция Unique_everseen () Может также использоваться со списками, содержащими смесью нерешительных и нерешимых элементов (думаю, что целые числа и поплавки), что является настоящим бонусом. Попытка предоставить ключ в этом случае приведет к Типеррор хоть.

Метод 6 – Numpy Уникальный ()

Если вы работаете с численными данными, сторонняя библиотека NUMPY тоже является опцией:

 >>> import numpy as np
 >>> initial = np.array([1, 1, 9, 1, 9, 6, 9, 7])
 >>> _, idx = np.unique(initial, return_index=True)
 >>> result = initial[np.sort(idx)]
 >>> result
 
 [1 9 6 7]

Значения индекса уникальных элементов могут быть сохранены с помощью np.unique () Функция с return_index Параметр установлен на Правда Отказ

Затем их можно передавать np.sort () Для получения правильно упорядоченного куска с дубликатами удалены.

Технически этот метод может быть применен к стандартному списку, сначала преобразовав его в Numpy Array, а затем преобразование его обратно в формат списка в конце. Однако это будет чрезмерный и неэффективный способ достижения результата.

Использование этих методов действительно имеет смысл, только если вы также используете мощные функции Numpy по другим причинам.

Метод 7 – Pandas Уникальный ()

Еще одна сторонняя библиотека, которую мы могли бы использовать, это Pandas:

 >>> import pandas as pd
 >>> initial = pd.Series([1, 1, 9, 1, 9, 6, 9, 7])
 >>> result = pd.unique(initial)
 >>> result
 
 [1 9 6 7]

Пандас лучше подходит для задачи, потому что он сохраняет порядок по умолчанию и pd.unique () значительно быстрее, чем np.unique () Отказ

Как и в случае Numpy методом, было бы совершенно возможно преобразовать результат в стандартный список в конце.

Опять же, если вы не используете удивительные инструменты анализа данных, предоставленные Pands для другой цели, нет очевидной причины выбрать этот подход по поводу еще более быстрой опции, используя встроенный тип данных Python, используя встроенный тип данных ( Метод 4 ) Отказ

Резюме

Как мы уже видели, существует широкий спектр способов решения этой проблемы и решение о том, о котором можно выбрать, должно быть обусловлено вашим конкретным обстоятельствами.

Если вы пишете быстрый скрипт, и ваш список не огромен, вы можете использовать простой для цикла для ясности.

Однако, если эффективность является фактором, и ваши списки не содержат смежные предметы, а затем идут с Dict.Fromkeys () это отличный вариант. Здорово, что этот метод использует один из встроенных типов данных Python и сохраняет хороший уровень читабельности, одновременно улучшающий скорость для скорости цикла.

Кроме того, если вы используете старую версию Python, Underduddict.Fromkeys () действительно хороший выбор, поскольку все еще очень быстро.

Если вам нужно работать со списками, которые содержат смежные элементы, импортируя больше-iTertools, чтобы вы могли воспользоваться Brilliant Unique_everseen () Функция имеет много смысла.

Наконец, если вы занимаетесь серьезным числом, хрустающим с помощью Numpy или Manipulatulation данных с Pandas, это, вероятно, было бы мудрое пойти с методами, встроенными в эти инструменты для этой цели.

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