Как я могу найти дубликаты в списке Python и создать другой список дубликатов? Список содержит только целые числа.
python
list
duplicates
MFB
источник
источник
Ответы:
Для удаления дубликатов используйте
set(a)
. Чтобы напечатать дубликаты, что-то вроде:Обратите внимание , что
Counter
это не особенно эффективным ( тайминги ) и , вероятно , избыточна здесь.set
будет работать лучше. Этот код вычисляет список уникальных элементов в исходном порядке:или, более кратко:
Я не рекомендую последний стиль, потому что не очевидно, что
not seen.add(x)
происходит (add()
метод set всегда возвращаетNone
, следовательно, необходимостьnot
).Чтобы вычислить список дублированных элементов без библиотек:
Если элементы списка не могут быть хешируемыми, вы не можете использовать наборы / dicts и вынуждены прибегать к решению с квадратичным временем (сравните каждый с каждым). Например:
источник
O(n)
, что это так, потому что он повторяет список только один раз и устанавливает поискO(1)
.dup = []
else: dup.append(x)
print()
seen = set()
тогдаdupe = set(x for x in a if x in seen or seen.add(x))
источник
l
сset(l)
только сокращает время сложности в худшем случае и , следовательно , не делает ничего для решения более масштабных проблем эффективности с этим ответом. Вероятно, все было не так просто. Короче, не делай этого.Вы не нуждаетесь в подсчете, просто независимо от того, был ли предмет виден раньше. Адаптировал этот ответ к этой проблеме:
На случай, если скорость имеет значение, вот некоторые моменты:
Вот результаты: (молодец @JohnLaRooy!)
Интересно, что, кроме самого времени, ранжирование немного меняется при использовании pypy. Самое интересное, что основанный на Counter подход очень сильно выигрывает от оптимизации pypy, тогда как предложенный мной подход к кэшированию методов, похоже, почти не дает эффекта.
Очевидно, этот эффект связан с «дублированием» входных данных. Я установил
l = [random.randrange(1000000) for i in xrange(10000)]
и получил эти результаты:источник
add
каждый раз, когда потребуется вставка.pypy
если она тебе пригодится и ты собираешься на скорость.Вы можете использовать
iteration_utilities.duplicates
:или если вы хотите только один из каждого дубликата, это может быть объединено с
iteration_utilities.unique_everseen
:Он также может обрабатывать непредсказуемые элементы (однако за счет производительности):
Это то, с чем могут справиться только некоторые другие подходы.
Ориентиры
Я сделал быстрый тест, содержащий большинство (но не все) подходов, упомянутых здесь.
Первый бенчмарк включал лишь небольшой диапазон длин списков, потому что некоторые подходы
O(n**2)
поведение.На графиках ось Y представляет время, поэтому меньшее значение означает лучшее. Он также построил log-log, так что широкий диапазон значений можно лучше визуализировать:
Удаляя
O(n**2)
подходы, я сделал еще один тест до полумиллиона элементов в списке:Как вы можете видеть,
iteration_utilities.duplicates
подход быстрее, чем любой другой подход и даже цепочкиunique_everseen(duplicates(...))
было быстрее или одинаково быстрым, чем другие подходы.Еще одна интересная вещь, которую следует здесь отметить, заключается в том, что подходы панд очень медленны для небольших списков, но могут легко конкурировать за более длинные списки.
Однако, как показывают эти тесты, большинство подходов работают примерно одинаково, поэтому не имеет значения, какой из них используется (за исключением 3, которые имели
O(n**2)
время выполнения).Контрольный показатель 1
Контрольный показатель 2
отказ
1 Это из библиотеки третьей стороной я написал:
iteration_utilities
.источник
Я сталкивался с этим вопросом, глядя на что-то связанное - и удивляюсь, почему никто не предложил решение на основе генератора? Решение этой проблемы будет:
Я был обеспокоен масштабируемостью, поэтому протестировал несколько подходов, включая наивные элементы, которые хорошо работают в небольших списках, но ужасно масштабируются по мере увеличения списков (примечание - было бы лучше использовать timeit, но это иллюстративно).
Я включил @moooeeeep для сравнения (он впечатляюще быстр: самый быстрый, если входной список полностью случайный) и подход itertools, который еще быстрее снова для большинства отсортированных списков ... Теперь включает в себя подход панд из @firelynx - медленно, но не ужасно так и просто. Примечание. Подход сортировки / тройника / почтового индекса на моей машине всегда самый быстрый для больших, в основном, упорядоченных списков, moooeeeep - самый быстрый для перемешанных списков, но ваш пробег может отличаться.
преимущества
Предположения
Самое быстрое решение, 1м записей:
Подходы проверены
Результаты теста «все дубликаты» были согласованы, и в этом массиве были обнаружены «сначала» дубликаты, а затем «все дубликаты»:
Когда списки перетасовываются первыми, цена сортировки становится очевидной - эффективность заметно падает, и подход @moooeeeep доминирует, при этом подходы set & dict похожи, но с меньшими показателями:
источник
random.shuffle(c)
учитывать это. Кроме того, я не могу воспроизвести ваши результаты при запуске неизмененного скрипта (абсолютно другой порядок), поэтому, возможно, это также зависит от процессора.Используя панд:
источник
collection.Counter является новым в Python 2.7:
В более ранней версии вы можете использовать вместо этого обычный dict:
источник
Вот аккуратное и краткое решение -
источник
Я бы сделал это с пандами, потому что я часто использую панд
дает
Возможно, он не очень эффективен, но в нем меньше кода, чем во многих других ответах, поэтому я решил внести свой вклад
источник
pda = pd.Series(a)
print list(pda[pda.duplicated()])
Без преобразования в список и, вероятно, самый простой способ будет что-то вроде ниже. Это может быть полезно во время интервью, когда они просят не использовать наборы
======= еще, чтобы получить 2 отдельных списка уникальных значений и дубликатов значений
источник
третий пример принятого ответа дает ошибочный ответ и не пытается дать дубликаты. Вот правильная версия:
источник
Как насчет просто пройтись по каждому элементу в списке, проверив количество вхождений, а затем добавив их в набор, который затем напечатает дубликаты. Надеюсь, это поможет кому-то там.
источник
Мы можем использовать
itertools.groupby
для того, чтобы найти все предметы, которые имеют дупс:Выход будет:
источник
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Я думаю, что наиболее эффективный способ найти дубликаты в списке:
Он использует
Counter
все элементы и все уникальные элементы. Вычитание первого со вторым исключит только дубликаты.источник
Немного поздно, но, возможно, полезно для некоторых. Для большого списка я нашел, что это работало для меня.
Показывает как раз и все дубликаты и сохраняет порядок.
источник
Очень простой и быстрый способ найти дубликаты за одну итерацию в Python:
Вывод будет следующим:
Это и многое другое в моем блоге http://www.howtoprogramwithpython.com
источник
Я вступаю намного позже в эту дискуссию. Хотя я бы хотел решить эту проблему с одним вкладышем. Потому что это прелесть Python. если мы просто хотим поместить дубликаты в отдельный список (или любую коллекцию), я бы предложил сделать это следующим образом. Скажем, у нас есть дублированный список, который мы можем назвать «целевым»
Теперь, если мы хотим получить дубликаты, мы можем использовать один вкладыш, как показано ниже:
Этот код будет помещать дублированные записи в качестве ключа и считать как значение в словарь «дубликаты». «Дубликат» словарь будет выглядеть следующим образом:
Если вы просто хотите, чтобы все записи с дубликатами содержались в списке, это снова намного более короткий код:
Выход будет:
Это прекрасно работает в версиях Python 2.7.x +
источник
Python 3.8, если вы не хотите писать собственный алгоритм или использовать библиотеки:
Печатает товар и считает:
groupby
принимает функцию группировки, чтобы вы могли определять свои группировки различными способами и возвращать дополнительныеTuple
поля по мере необходимости.groupby
ленивый, поэтому он не должен быть слишком медленнымисточник
Некоторые другие тесты. Конечно делать ...
... это слишком дорого Примерно в 500 раз быстрее (чем длиннее массив дает лучшие результаты), тем лучше использовать следующий последний метод:
Только 2 петли, не очень дорого
l.count()
операций.Вот код для сравнения методов, например. Код ниже, вот вывод:
Код тестирования:
источник
Способ 1:
Объяснение: [val для idx, val в enumerate (input_list), если val в input_list [idx + 1:]] является представлением списка, которое возвращает элемент, если тот же элемент присутствует из его текущей позиции, в списке, индексе ,
Пример: input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
начиная с первого элемента в списке 42, с индексом 0, он проверяет, присутствует ли элемент 42 в input_list [1:] (то есть от индекса 1 до конца списка), поскольку 42 присутствует в input_list [1:] , вернется 42.
Затем он переходит к следующему элементу 31 с индексом 1 и проверяет, присутствует ли элемент 31 в input_list [2:] (то есть от индекса 2 до конца списка), поскольку 31 присутствует в input_list [2:], вернется 31.
Точно так же он проходит через все элементы в списке и возвращает в список только повторяющиеся / повторяющиеся элементы.
Затем, поскольку у нас есть дубликаты, в списке нам нужно выбрать один из каждого дубликата, то есть удалить дубликаты среди дубликатов, и для этого мы вызываем встроенный в python named с именем set (), и он удаляет дубликаты,
Затем у нас остается набор, но не список, и, следовательно, для преобразования из набора в список мы используем typecasting, list (), и это преобразует набор элементов в список.
Способ 2:
Пояснение: Здесь мы создаем два пустых списка, для начала. Затем продолжайте просмотр всех элементов списка, чтобы увидеть, существует ли он в temp_list (изначально пустом). Если его нет в temp_list, мы добавляем его в temp_list, используя метод append .
Если он уже существует в temp_list, это означает, что текущий элемент списка является дубликатом, и, следовательно, нам нужно добавить его в dupe_list с помощью метода append .
источник
Вы в основном удаляете дубликаты путем преобразования в set (
clean_list
), затем выполняете итерациюraw_list
, удаляя каждыйitem
в чистом списке для появления вraw_list
. Еслиitem
он не найден, возникшееValueError
исключение перехватывается иitem
добавляется вduplicated_items
список.Если нужен индекс дублированных элементов, просто
enumerate
составьте список и поиграйте с индексом. (for index, item in enumerate(raw_list):
), который быстрее и оптимизирован для больших списков (например, тысячи + элементов)источник
использование
list.count()
метода в списке, чтобы найти дубликаты элементов данного спискаисточник
одна строка, для развлечения, и где требуется одно утверждение.
источник
источник
Одноканальное решение:
источник
Здесь есть много ответов, но я думаю, что это относительно легко читаемый и простой для понимания подход:
Ноты:
источник
Вот быстрый генератор, который использует dict для хранения каждого элемента в качестве ключа с логическим значением для проверки, был ли дублированный элемент уже получен.
Для списков со всеми элементами, которые являются типами hashable:
Для списков, которые могут содержать списки:
источник
источник
При использовании toolz :
источник
это был способ, которым я должен был сделать, потому что я бросил себе вызов не использовать другие методы:
так что ваш образец работает как:
источник
duplist = list(set(a))
.