В значительной степени мне нужно написать программу, чтобы проверить, есть ли в списке дубликаты, и если он это делает, он удаляет их и возвращает новый список с элементами, которые не были дублированы / удалены. Это то, что у меня есть, но, если честно, я не знаю, что делать.
def remove_duplicates():
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
for t in t2:
t.append(t.remove())
return t
python
algorithm
list
duplicates
intersection
Neemaximo
источник
источник
Ответы:
Обычный подход для получения уникальной коллекции предметов заключается в использовании
set
. Наборы - это неупорядоченные наборы отдельных объектов. Чтобы создать набор из любого итератора, вы можете просто передать его встроеннойset()
функции. Если позже вам снова понадобится реальный список, вы можете аналогичным образом передать набор вlist()
функцию.Следующий пример должен охватывать все, что вы пытаетесь сделать:
Как видно из примера, исходный порядок не поддерживается . Как упоминалось выше, сами наборы являются неупорядоченными коллекциями, поэтому порядок теряется. При преобразовании набора обратно в список создается произвольный порядок.
Поддержание порядка
Если порядок важен для вас, вам придется использовать другой механизм. Очень распространенным решением для этого является
OrderedDict
сохранение порядка ключей во время вставки:Начиная с Python 3.7 , встроенный словарь гарантированно поддерживает порядок вставки, так что вы также можете использовать его напрямую, если вы используете Python 3.7 или более позднюю версию (или CPython 3.6):
Обратите внимание, что это может привести к определенным накладным расходам: сначала создать словарь, а затем создать из него список. Если вам на самом деле не нужно сохранять порядок, вам часто лучше использовать набор, особенно потому, что он дает вам гораздо больше операций для работы. Проверьте этот вопрос для более подробной информации и альтернативных способов сохранить порядок при удалении дубликатов.
Наконец, обратите внимание, что как решения,
set
так иOrderedDict
/dict
требуют, чтобы ваши элементы были хэшируемыми . Обычно это означает, что они должны быть неизменными. Если вам приходится иметь дело с элементами, которые не могут быть хешируемыми (например, списочные объекты), то вам придется использовать медленный подход, при котором вам придется сравнивать каждый элемент с любым другим элементом во вложенном цикле.источник
В Python 2.7 новый способ удаления дубликатов из итерируемого при сохранении его в исходном порядке:
В Python 3.5 OrderedDict имеет реализацию на языке C. Мои данные показывают, что сейчас это самый быстрый и самый короткий из различных подходов для Python 3.5.
В Python 3.6 обычный dict стал упорядоченным и компактным. (Эта функция поддерживается для CPython и PyPy, но может отсутствовать в других реализациях). Это дает нам новый самый быстрый способ дедупликации при сохранении порядка:
В Python 3.7 регулярный dict гарантированно упорядочен во всех реализациях. Итак, самое короткое и быстрое решение:
источник
TypeError: unhashable type: 'dictlist'
Это однострочник:
list(set(source_list))
сделает свое дело.А
set
это то, что не может иметь дубликаты.Обновление: подход к сохранению порядка состоит из двух строк:
Здесь мы используем тот факт, что
OrderedDict
запоминает порядок вставки ключей и не изменяет его при обновлении значения для определенного ключа. Мы вставляем вTrue
качестве значений, но мы можем вставить что угодно, значения просто не используются. (set
работает так же, как иdict
с игнорируемыми значениями.)источник
source_list
можно хэшировать.источник
frozenset
работает с нехэш-содержимым. Я все еще получаю не хэш-ошибку при использованииfrozenset
.Если вы не заботитесь о заказе, просто сделайте это:
А
set
гарантированно не будет дубликатов.источник
l
является хэшируемым.Составить новый список, сохраняющий порядок первых элементов дубликатов в
L
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]
например
if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]
тогдаnewlist
будет[1,2,3,4,5]
Это проверяет, что каждый новый элемент ранее не появлялся в списке перед его добавлением. Также не нуждается в импорте.
источник
set
иOrderedDict
могут иметь меньшую сложность амортизированного времени.Коллега прислал мне принятый ответ как часть своего кода для сегодняшнего просмотра кода. Хотя я, конечно, восхищаюсь элегантностью рассматриваемого ответа, я не доволен работой. Я пробовал это решение (я использую набор для сокращения времени поиска)
Для сравнения эффективности я использовал случайную выборку из 100 целых чисел - 62 были уникальными
Вот результаты измерений
Что произойдет, если набор будет удален из решения?
Результат не так плох, как с OrderedDict , но все же более чем в 3 раза превышает исходное решение.
источник
def unique(iterable):
:;seen = set()
;seen_add = seen.add
;return [item for item in iterable if not item in seen and not seen_add(item)]
Есть также решения, использующие Pandas и Numpy. Они оба возвращают массив NumPy, поэтому вы должны использовать функцию,
.tolist()
если вы хотите список.Решение панд
Используя функцию Pandas
unique()
:Numpy решение
Используя функцию NumPy
unique()
.Обратите внимание, что numpy.unique () также сортирует значения . Таким образом, список
t2
возвращается отсортированным. Если вы хотите сохранить порядок, используйте как в этом ответе :Решение не столь элегантно по сравнению с другими, однако, по сравнению с pandas.unique (), numpy.unique () позволяет также проверить, являются ли вложенные массивы уникальными вдоль одной выбранной оси.
источник
Еще один способ сделать:
источник
keys()
возвращает объект представления словаря, а не список.Просто и легко:
Вывод:
источник
in
это операция O (n), и у васcleanlist
будет не болееn
чисел => наихудший случай ~ O (n ^ 2)В этом ответе будут два раздела: два уникальных решения и график скорости для конкретных решений.
Удаление дубликатов
В большинстве из этих ответов удаляются только дублирующиеся элементы, которые можно хэшировать , но этот вопрос не означает, что ему нужны не только хэшируемые элементы, а это означает, что я предложу некоторые решения, которые не требуют хэшируемых элементов.
collection.Counter - это мощный инструмент в стандартной библиотеке, который идеально подходит для этого. Есть только одно решение, в котором даже есть Counter. Однако это решение также ограничено хэшируемыми ключами.
Чтобы разрешить неиспользуемые ключи в Counter, я создал класс Container, который попытается получить хеш-функцию объекта по умолчанию, но в случае сбоя он попытается использовать функцию идентификации. Он также определяет eq и метод хэширования . Этого должно быть достаточно, чтобы в нашем решении не было нежелательных предметов. Нежелательные объекты будут обрабатываться так, как если бы они были хешеными. Тем не менее, эта хеш-функция использует идентичность для не подлежащих обработке объектов, а это означает, что два равных объекта, которые оба не подлежат обработке, не будут работать. Я предлагаю вам переопределить это и изменить его на использование хэша эквивалентного изменяемого типа (например, использование
hash(tuple(my_list))
ifmy_list
is is list).Я также сделал два решения. Другое решение, которое поддерживает порядок элементов, используя подкласс OrderedDict и Counter, который называется OrderedCounter. Теперь вот функции:
remd - неупорядоченная сортировка, oremd - упорядоченная сортировка. Вы можете четко сказать, какой из них быстрее, но я все равно объясню. Неупорядоченная сортировка немного быстрее. Он хранит меньше данных, так как не нуждается в порядке.
Теперь я также хотел показать сравнение скорости каждого ответа. Итак, я сделаю это сейчас.
Какая функция самая быстрая?
Для удаления дубликатов я собрал 10 функций из нескольких ответов. Я рассчитал скорость каждой функции и поместил ее в график, используя matplotlib.pyplot .
Я разделил это на три этапа построения графиков. Хэшируемый - это любой объект, который может быть хэширован, а неэхируемый - это любой объект, который не может быть хеширован. Упорядоченная последовательность - это последовательность, которая сохраняет порядок, неупорядоченная последовательность не сохраняет порядок. Теперь, вот еще несколько терминов:
Unordered Hashable был для любого метода, который удалял дубликаты, которые не обязательно должны поддерживать порядок. Это не должно было работать на непоправимые последствия, но могло.
Ordered Hashable предназначался для любого метода, который сохранял порядок элементов в списке, но он не должен был работать для непоправимых предметов, но мог.
Ordered Unhashable - это любой метод, который сохраняет порядок элементов в списке и работает на непоправимые убытки.
На оси Y указано количество секунд, которое потребовалось.
На оси абсцисс - номер, к которому была применена функция.
Мы сгенерировали последовательности для неупорядоченных хеш-хэлов и упорядоченных хеш-хеллов со следующим пониманием:
[list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Для заказанных небрежных предметов:
[[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Обратите внимание, что в диапазоне есть «шаг», потому что без него это заняло бы 10x больше времени. Кроме того, потому что, по моему личному мнению, я думал, что это могло бы выглядеть немного легче для чтения.
Также обратите внимание, что ключи на легенде - это то, что я пытался угадать как наиболее важные части функции. Что за функцию выполняет худший или лучший? График говорит сам за себя.
С этим улажено, вот графики.
Неупорядоченные хешаблы
(Увеличено)
Заказал Hashables
(Увеличено)
Заказано Небрежно
(Увеличено)
источник
У меня был дикт в моем списке, поэтому я не мог использовать вышеупомянутый подход. Я получил ошибку:
Так что если вы заботитесь о заказе и / или некоторые предметы не подлежат уничтожению . Тогда вы можете найти это полезным:
Некоторые могут посчитать, что понимание списка с побочным эффектом не является хорошим решением. Вот альтернатива:
источник
map
с побочным эффектом еще более вводит в заблуждение, чем listcomp с побочным эффектом. Кроме того,lambda x: unique_list.append(x)
это просто более медленный и медленный способ пройтиunique_list.append
.Все подходы к сохранению порядка, которые я видел здесь до сих пор, используют либо наивное сравнение (в лучшем случае с O (n ^ 2) сложностью времени), либо комбинации с большим весом
OrderedDicts
/set
+list
, которые ограничены хэшируемыми входными данными. Вот решение, не зависящее от хэша: O (nlogn):Обновление добавил
key
аргумент, документацию и совместимость с Python 3.источник
tuple()
списков и их хэширования. | | | | - Вообще говоря, процесс хеширования занимает время, пропорциональное размеру целых данных, тогда как это решение занимает время O (nlog (n)), зависящее только от длины списка.reduce()
Уже работают над отсортированными коллекциямиsrt_enum
, почему вы подали заявкуsorted
снова?Если вы хотите сохранить порядок и не использовать какие-либо внешние модули, вот простой способ сделать это:
Примечание. Этот метод сохраняет порядок появления, поэтому, как показано выше, девять будут приходить после одного, потому что это был первый раз, когда он появился. Это, однако, тот же результат, который вы получили бы при выполнении
но он намного короче и работает быстрее.
Это работает, потому что каждый раз, когда
fromkeys
функция пытается создать новый ключ, если значение уже существует, оно просто перезаписывает его. Однако это никак не повлияет на словарь, посколькуfromkeys
создает словарь, в котором все ключи имеют значениеNone
, поэтому эффективно удаляет все дубликаты таким образом.источник
Вы также можете сделать это:
Причина, по которой работает выше, заключается в том, что
index
метод возвращает только первый индекс элемента. Повторяющиеся элементы имеют более высокие показатели. Обратитесь сюда :источник
list.index
является линейной операцией, делающей ваше решение квадратичным.Попробуйте использовать наборы:
источник
Сократить вариант с заказом консервирования:
Предположим, что у нас есть список:
Уменьшить вариант (неэффективно):
В 5 раз быстрее, но сложнее
Объяснение:
источник
Лучший подход к удалению дубликатов из списка - использование функции set () , доступной в python, и снова преобразование этого набора в список.
источник
Вы можете использовать следующую функцию:
Пример :
Применение:
['this', 'is', 'a', 'list', 'with', 'dupicates', 'in', 'the']
источник
Есть много других ответов, предлагающих разные способы сделать это, но все они являются пакетными операциями, и некоторые из них отбрасывают первоначальный порядок. Это может быть хорошо в зависимости от того, что вам нужно, но если вы хотите перебирать значения в порядке первого экземпляра каждого значения, и вы хотите удалить дубликаты на лету по сравнению со всеми сразу, вы можете использовать этот генератор:
Это возвращает генератор / итератор, так что вы можете использовать его везде, где вы можете использовать итератор.
Вывод:
Если вы хотите
list
, вы можете сделать это:Вывод:
источник
seen = set(iterable); for item in seen: yield item
почти наверняка быстрее. (Я не пробовал этот конкретный случай, но это было бы мое предположение.)Без использования набора
источник
Вы можете использовать
set
для удаления дубликатов:Но обратите внимание, что результаты будут неупорядоченными. Если это проблема:
источник
Еще один лучший подход может быть,
и порядок остается сохраненным.
источник
Этот заботится о заказе без особых хлопот (OrderdDict и другие). Вероятно, не самый Pythonic способ, ни кратчайший путь, но делает трюк:
источник
list
); 2. Ваш метод очень плохо масштабируется: он квадратичен по количеству элементов вlist
.код ниже прост для удаления дубликатов в списке
возвращается [1,2,3,4]
источник
list(set(..))
(более 1 миллиона проходов) побьет это решение примерно на 10 полных секунд - тогда как этот подход занимает около 12 секунд,list(set(..))
всего около 2 секунд!Вот самое быстрое питоническое решение, сопоставляемое с другими, перечисленными в ответах.
Использование деталей реализации оценки короткого замыкания позволяет использовать понимание списка, что достаточно быстро.
visited.add(item)
всегда возвращаетNone
результат, который оценивается какFalse
, поэтому правая частьor
всегда будет результатом такого выражения.Время сам
источник
Используя набор :
Используя уникальные :
источник
К несчастью. Большинство ответов здесь либо не сохраняют порядок, либо являются слишком длинными. Вот простой ответ, сохраняющий порядок.
Это даст вам х с удаленными дубликатами, но сохраняя порядок.
источник
Очень простой способ в Python 3:
источник
sorted(list(...))
является избыточным (sorted
уже неявно преобразует свой аргумент в новыйlist
, сортирует его, затем возвращает новыйlist
, поэтому использование обоих способов делает ненужное временноеlist
). Используйте только,list
если результат не нужно сортировать, используйте только,sorted
если результат должен быть отсортирован.Магия Питона Встроенный тип
В python очень легко обрабатывать сложные случаи, подобные этому, и только по встроенному типу python.
Позвольте мне показать вам, как это сделать!
Метод 1: Общий случай
Способ ( 1-строчный код ) удалить дублирующийся элемент в списке и сохранить порядок сортировки
Вы получите результат
Способ 2: особый случай
Особый случай для обработки небрежного ( 3 строки кода )
Вы получите результат:
Потому что кортеж является хэшируемым, и вы можете легко конвертировать данные между списком и кортежем
источник