Как найти дубликаты в списке и создать с ними другой список?

Как найти дубликаты в списке Python и создать другой список дубликатов? Список содержит только целые числа.

Ответ 1

Для удаления дубликатов используйте set(a). Чтобы напечатать дубликаты, что-то вроде:

a = [1,2,3,2,1,5,6,5,5,5]

import collections
print [item for item, count in collections.Counter(a).items() if count > 1]

## [1, 2, 5]

Обратите внимание, что Counter не особенно эффективен (тайминги) и, вероятно, излишний set будет работать лучше. Этот код вычисляет список уникальных элементов в исходном порядке:

seen = set()
uniq = []
for x in a:
    if x not in seen:
        uniq.append(x)
        seen.add(x)

или, более кратко:

seen = set()
uniq = [x for x in a if x not in seen and not seen.add(x)]    

Я не рекомендую последний стиль, потому что не очевидно, что делает not seen.add(x) (метод set add() всегда возвращает None, следовательно, not).

Чтобы вычислить список дублированных элементов без библиотек:

seen = {}
dupes = []

for x in a:
    if x not in seen:
        seen[x] = 1
    else:
        if seen[x] == 1:
            dupes.append(x)
        seen[x] += 1

Если элементы списка не могут быть хешируемыми, вы не можете использовать наборы /dicts и вынуждены прибегать к решению с квадратичным временем (сравните каждый с каждым). Например:

a = [[1], [2], [3], [1], [5], [3]]

no_dupes = [x for n, x in enumerate(a) if x not in a[:n]]
print no_dupes # [[1], [2], [3], [5]]

dupes = [x for n, x in enumerate(a) if x in a[:n]]
print dupes # [[1], [3]]

Ответ 2

>>> l = [1,2,3,4,4,5,5,6,1]
>>> set([x for x in l if l.count(x) > 1])
set([1, 4, 5])

Ответ 3

Вам не нужен счет, только если элемент был замечен раньше. Адаптировано чтобы ответить на эту проблему:

def list_duplicates(seq):
  seen = set()
  seen_add = seen.add
  # adds all elements it doesn't know yet to seen and all other to seen_twice
  seen_twice = set( x for x in seq if x in seen or seen_add(x) )
  # turn the set into a list (as requested)
  return list( seen_twice )

a = [1,2,3,2,1,5,6,5,5,5]
list_duplicates(a) # yields [1, 2, 5]

На всякий случай скорость имеет значение, вот некоторые тайминги:

# file: test.py
import collections

def thg435(l):
    return [x for x, y in collections.Counter(l).items() if y > 1]

def moooeeeep(l):
    seen = set()
    seen_add = seen.add
    # adds all elements it doesn't know yet to seen and all other to seen_twice
    seen_twice = set( x for x in l if x in seen or seen_add(x) )
    # turn the set into a list (as requested)
    return list( seen_twice )

def RiteshKumar(l):
    return list(set([x for x in l if l.count(x) > 1]))

def JohnLaRooy(L):
    seen = set()
    seen2 = set()
    seen_add = seen.add
    seen2_add = seen2.add
    for item in L:
        if item in seen:
            seen2_add(item)
        else:
            seen_add(item)
    return list(seen2)

l = [1,2,3,2,1,5,6,5,5,5]*100

Вот результаты: (хорошо сделано @JohnLaRooy!)

$ python -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
10000 loops, best of 3: 74.6 usec per loop
$ python -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
10000 loops, best of 3: 91.3 usec per loop
$ python -mtimeit -s 'import test' 'test.thg435(test.l)'
1000 loops, best of 3: 266 usec per loop
$ python -mtimeit -s 'import test' 'test.RiteshKumar(test.l)'
100 loops, best of 3: 8.35 msec per loop

Интересно, что помимо самого тайминга, ранжирование немного меняется при использовании pypy. Самое интересное, что подход, основанный на Counter-адресе, чрезвычайно выгоден от оптимизации pypy, тогда как метод кэширования метода, который я предложил, практически не имеет эффекта.

$ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
100000 loops, best of 3: 17.8 usec per loop
$ pypy -mtimeit -s 'import test' 'test.thg435(test.l)'
10000 loops, best of 3: 23 usec per loop
$ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
10000 loops, best of 3: 39.3 usec per loop

Очевидно, этот эффект связан с "дублированием" входных данных. Я установил l = [random.randrange(1000000) for i in xrange(10000)] и получил следующие результаты:

$ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
1000 loops, best of 3: 495 usec per loop
$ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
1000 loops, best of 3: 499 usec per loop
$ pypy -mtimeit -s 'import test' 'test.thg435(test.l)'
1000 loops, best of 3: 1.68 msec per loop

Ответ 4

Я столкнулся с этим вопросом, обращаясь к чему-то связанному, и задаюсь вопросом, почему никто не предложил решение на базе генератора? Решение этой проблемы:

>>> print list(getDupes_9([1,2,3,2,1,5,6,5,5,5]))
[1, 2, 5]

Я занимался масштабируемостью, поэтому проверял несколько подходов, в том числе наивные элементы, которые хорошо работают в небольших списках, но масштабируются ужасно по мере увеличения списков (обратите внимание - лучше было бы использовать timeit, но это иллюстративно).

Я включил @moooeeeep для сравнения (это впечатляюще быстро: быстрее, если список ввода полностью случайный) и подход itertools, который еще быстрее повторяет для отсортированных списков... Теперь включает подход pandas от @firelynx - - медленный, но не ужасно, и простой. Примечание. Метод sort/tee/zip является самым быстрым на моей машине для больших в основном упорядоченных списков, moooeeeep является самым быстрым для перетасованных списков, но ваш пробег может отличаться.

<сильные > Преимущества

  • очень быстрая проверка для "любых" дубликатов с использованием того же кода

Предположения

  • Дубликаты должны сообщаться только один раз
  • Дублировать порядок не нужно.
  • Дубликат может быть в любом месте списка

Самое быстрое решение, 1 м записей:

def getDupes(c):
        '''sort/tee/izip'''
        a, b = itertools.tee(sorted(c))
        next(b, None)
        r = None
        for k, g in itertools.izip(a, b):
            if k != g: continue
            if k != r:
                yield k
                r = k

Проверены подходы

import itertools
import time
import random

def getDupes_1(c):
    '''naive'''
    for i in xrange(0, len(c)):
        if c[i] in c[:i]:
            yield c[i]

def getDupes_2(c):
    '''set len change'''
    s = set()
    for i in c:
        l = len(s)
        s.add(i)
        if len(s) == l:
            yield i

def getDupes_3(c):
    '''in dict'''
    d = {}
    for i in c:
        if i in d:
            if d[i]:
                yield i
                d[i] = False
        else:
            d[i] = True

def getDupes_4(c):
    '''in set'''
    s,r = set(),set()
    for i in c:
        if i not in s:
            s.add(i)
        elif i not in r:
            r.add(i)
            yield i

def getDupes_5(c):
    '''sort/adjacent'''
    c = sorted(c)
    r = None
    for i in xrange(1, len(c)):
        if c[i] == c[i - 1]:
            if c[i] != r:
                yield c[i]
                r = c[i]

def getDupes_6(c):
    '''sort/groupby'''
    def multiple(x):
        try:
            x.next()
            x.next()
            return True
        except:
            return False
    for k, g in itertools.ifilter(lambda x: multiple(x[1]), itertools.groupby(sorted(c))):
        yield k

def getDupes_7(c):
    '''sort/zip'''
    c = sorted(c)
    r = None
    for k, g in zip(c[:-1],c[1:]):
        if k == g:
            if k != r:
                yield k
                r = k

def getDupes_8(c):
    '''sort/izip'''
    c = sorted(c)
    r = None
    for k, g in itertools.izip(c[:-1],c[1:]):
        if k == g:
            if k != r:
                yield k
                r = k

def getDupes_9(c):
    '''sort/tee/izip'''
    a, b = itertools.tee(sorted(c))
    next(b, None)
    r = None
    for k, g in itertools.izip(a, b):
        if k != g: continue
        if k != r:
            yield k
            r = k

def getDupes_a(l):
    '''moooeeeep'''
    seen = set()
    seen_add = seen.add
    # adds all elements it doesn't know yet to seen and all other to seen_twice
    for x in l:
        if x in seen or seen_add(x):
            yield x

def getDupes_b(x):
    '''iter*/sorted'''
    x = sorted(x)
    def _matches():
        for k,g in itertools.izip(x[:-1],x[1:]):
            if k == g:
                yield k
    for k, n in itertools.groupby(_matches()):
        yield k

def getDupes_c(a):
    '''pandas'''
    import pandas as pd
    vc = pd.Series(a).value_counts()
    i = vc[vc > 1].index
    for _ in i:
        yield _

def hasDupes(fn,c):
    try:
        if fn(c).next(): return True    # Found a dupe
    except StopIteration:
        pass
    return False

def getDupes(fn,c):
    return list(fn(c))

STABLE = True
if STABLE:
    print 'Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array'
else:
    print 'Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array'
for location in (50,250000,500000,750000,999999):
    for test in (getDupes_2, getDupes_3, getDupes_4, getDupes_5, getDupes_6,
                 getDupes_8, getDupes_9, getDupes_a, getDupes_b, getDupes_c):
        print 'Test %-15s:%10d - '%(test.__doc__ or test.__name__,location),
        deltas = []
        for FIRST in (True,False):
            for i in xrange(0, 5):
                c = range(0,1000000)
                if STABLE:
                    c[0] = location
                else:
                    c.append(location)
                    random.shuffle(c)
                start = time.time()
                if FIRST:
                    print '.' if location == test(c).next() else '!',
                else:
                    print '.' if [location] == list(test(c)) else '!',
                deltas.append(time.time()-start)
            print ' -- %0.3f  '%(sum(deltas)/len(deltas)),
        print
    print

Результаты теста "all dupes" были согласованы, в результате поиска "первых" дубликатов, а затем "всех" дубликатов в этом массиве:

Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array
Test set len change :    500000 -  . . . . .  -- 0.264   . . . . .  -- 0.402  
Test in dict        :    500000 -  . . . . .  -- 0.163   . . . . .  -- 0.250  
Test in set         :    500000 -  . . . . .  -- 0.163   . . . . .  -- 0.249  
Test sort/adjacent  :    500000 -  . . . . .  -- 0.159   . . . . .  -- 0.229  
Test sort/groupby   :    500000 -  . . . . .  -- 0.860   . . . . .  -- 1.286  
Test sort/izip      :    500000 -  . . . . .  -- 0.165   . . . . .  -- 0.229  
Test sort/tee/izip  :    500000 -  . . . . .  -- 0.145   . . . . .  -- 0.206  *
Test moooeeeep      :    500000 -  . . . . .  -- 0.149   . . . . .  -- 0.232  
Test iter*/sorted   :    500000 -  . . . . .  -- 0.160   . . . . .  -- 0.221  
Test pandas         :    500000 -  . . . . .  -- 0.493   . . . . .  -- 0.499  

Когда списки сначала перетасовываются, цена сорта становится очевидной - эффективность заметно снижается, а подход @moooeeeep доминирует, при этом подходы set и dict похожи, но исполнители-лизингодатели:

Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array
Test set len change :    500000 -  . . . . .  -- 0.321   . . . . .  -- 0.473  
Test in dict        :    500000 -  . . . . .  -- 0.285   . . . . .  -- 0.360  
Test in set         :    500000 -  . . . . .  -- 0.309   . . . . .  -- 0.365  
Test sort/adjacent  :    500000 -  . . . . .  -- 0.756   . . . . .  -- 0.823  
Test sort/groupby   :    500000 -  . . . . .  -- 1.459   . . . . .  -- 1.896  
Test sort/izip      :    500000 -  . . . . .  -- 0.786   . . . . .  -- 0.845  
Test sort/tee/izip  :    500000 -  . . . . .  -- 0.743   . . . . .  -- 0.804  
Test moooeeeep      :    500000 -  . . . . .  -- 0.234   . . . . .  -- 0.311  *
Test iter*/sorted   :    500000 -  . . . . .  -- 0.776   . . . . .  -- 0.840  
Test pandas         :    500000 -  . . . . .  -- 0.539   . . . . .  -- 0.540  

Ответ 5

Вы можете использовать iteration_utilities.duplicates:

>>> from iteration_utilities import duplicates

>>> list(duplicates([1,1,2,1,2,3,4,2]))
[1, 1, 2, 2]

или если вы хотите только один из каждого дубликата, это можно объединить с iteration_utilities.unique_everseen:

>>> from iteration_utilities import unique_everseen

>>> list(unique_everseen(duplicates([1,1,2,1,2,3,4,2])))
[1, 2]

Он также может обрабатывать не сотрясаемые элементы (однако за счет производительности):

>>> list(duplicates([[1], [2], [1], [3], [1]]))
[[1], [1]]

>>> list(unique_everseen(duplicates([[1], [2], [1], [3], [1]])))
[[1]]

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

Ориентиры

Я сделал быстрый тест, содержащий большинство (но не всех) упомянутых здесь подходов.

Первый контрольный показатель включал только небольшой диапазон длин списков, поскольку некоторые подходы имеют поведение O(n**2).

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

enter image description here

Удаление подходов O(n**2) я сделал еще один ориентир до полумиллиона элементов в списке:

enter image description here

Поскольку вы можете видеть, что метод iteration_utilities.duplicates выполняется быстрее любого из других подходов и даже цепочки unique_everseen(duplicates(...)) был быстрее или одинаково быстрым, чем другие подходы.

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

Однако, поскольку эти контрольные показатели показывают, что большинство подходов выполняют примерно одинаково, поэтому не имеет большого значения, какой из них используется (за исключением 3, которые имели O(n**2) время исполнения).

from iteration_utilities import duplicates, unique_everseen
from collections import Counter
import pandas as pd
import itertools

def georg_counter(it):
    return [item for item, count in Counter(it).items() if count > 1]

def georg_set(it):
    seen = set()
    uniq = []
    for x in it:
        if x not in seen:
            uniq.append(x)
            seen.add(x)

def georg_set2(it):
    seen = set()
    return [x for x in it if x not in seen and not seen.add(x)]   

def georg_set3(it):
    seen = {}
    dupes = []

    for x in it:
        if x not in seen:
            seen[x] = 1
        else:
            if seen[x] == 1:
                dupes.append(x)
            seen[x] += 1

def RiteshKumar_count(l):
    return set([x for x in l if l.count(x) > 1])

def moooeeeep(seq):
    seen = set()
    seen_add = seen.add
    # adds all elements it doesn't know yet to seen and all other to seen_twice
    seen_twice = set( x for x in seq if x in seen or seen_add(x) )
    # turn the set into a list (as requested)
    return list( seen_twice )

def F1Rumors_implementation(c):
    a, b = itertools.tee(sorted(c))
    next(b, None)
    r = None
    for k, g in zip(a, b):
        if k != g: continue
        if k != r:
            yield k
            r = k

def F1Rumors(c):
    return list(F1Rumors_implementation(c))

def Edward(a):
    d = {}
    for elem in a:
        if elem in d:
            d[elem] += 1
        else:
            d[elem] = 1
    return [x for x, y in d.items() if y > 1]

def wordsmith(a):
    return pd.Series(a)[pd.Series(a).duplicated()].values

def NikhilPrabhu(li):
    li = li.copy()
    for x in set(li):
        li.remove(x)

    return list(set(li))

def firelynx(a):
    vc = pd.Series(a).value_counts()
    return vc[vc > 1].index.tolist()

def HenryDev(myList):
    newList = set()

    for i in myList:
        if myList.count(i) >= 2:
            newList.add(i)

    return list(newList)

def yota(number_lst):
    seen_set = set()
    duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x))
    return seen_set - duplicate_set

def IgorVishnevskiy(l):
    s=set(l)
    d=[]
    for x in l:
        if x in s:
            s.remove(x)
        else:
            d.append(x)
    return d

def it_duplicates(l):
    return list(duplicates(l))

def it_unique_duplicates(l):
    return list(unique_everseen(duplicates(l)))

Контрольный показатель 1

from simple_benchmark import benchmark
import random

funcs = [
    georg_counter, georg_set, georg_set2, georg_set3, RiteshKumar_count, moooeeeep, 
    F1Rumors, Edward, wordsmith, NikhilPrabhu, firelynx,
    HenryDev, yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates
]

args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 12)}

b = benchmark(funcs, args, 'list size')

b.plot()

Тест 2

funcs = [
    georg_counter, georg_set, georg_set2, georg_set3, moooeeeep, 
    F1Rumors, Edward, wordsmith, firelynx,
    yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates
]

args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 20)}

b = benchmark(funcs, args, 'list size')
b.plot()

отказ

1 Это из сторонней библиотеки, которую я написал: iteration_utilities.

Ответ 6

collections.Counter - новый в python 2.7:


Python 2.5.4 (r254:67916, May 31 2010, 15:03:39) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
a = [1,2,3,2,1,5,6,5,5,5]
import collections
print [x for x, y in collections.Counter(a).items() if y > 1]
Type "help", "copyright", "credits" or "license" for more information.
  File "", line 1, in 
AttributeError: 'module' object has no attribute 'Counter'
>>> 

В более ранней версии вы можете вместо этого использовать обычный dict:

a = [1,2,3,2,1,5,6,5,5,5]
d = {}
for elem in a:
    if elem in d:
        d[elem] += 1
    else:
        d[elem] = 1

print [x for x, y in d.items() if y > 1]

Ответ 7

Использование pandas:

>>> import pandas as pd
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> pd.Series(a)[pd.Series(a).duplicated()].values
array([1, 3, 3])

Ответ 8

Здесь аккуратное и сжатое решение -

for x in set(li):
    li.remove(x)

li = list(set(li))

Ответ 9

Я бы сделал это с помощью pandas, потому что я часто использую pandas

import pandas as pd
a = [1,2,3,3,3,4,5,6,6,7]
vc = pd.Series(a).value_counts()
vc[vc > 1].index.tolist()

дает

[3,6]

Вероятно, это не очень эффективно, но, конечно, это меньше кода, чем многие другие ответы, поэтому я думал, что внесет вклад

Ответ 10

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

number_lst = [1, 1, 2, 3, 5, ...]

seen_set = set()
duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x))
unique_set = seen_set - duplicate_set

Ответ 11

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

myList  = [2 ,4 , 6, 8, 4, 6, 12];
newList = set()

for i in myList:
    if myList.count(i) >= 2:
        newList.add(i)

print(list(newList))
## [4 , 6]

Ответ 12

Без преобразования в список и, вероятно, самый простой способ будет что-то вроде ниже. Это может быть полезно во время интервью, когда они просят не использовать наборы

a=[1,2,3,3,3]
dup=[]
for each in a:
  if each not in dup:
    dup.append(each)
print(dup)

======= еще, чтобы получить 2 отдельных списка уникальных значений и повторяющихся значений

a=[1,2,3,3,3]
uniques=[]
dups=[]

for each in a:
  if each not in uniques:
    uniques.append(each)
  else:
    dups.append(each)
print("Unique values are below:")
print(uniques)
print("Duplicate values are below:")
print(dups)

Ответ 13

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

l=[1,2,3,5,4,1,3,1]
s=set(l)
d=[]
for x in l:
    if x in s:
        s.remove(x)
    else:
        d.append(x)
d
[1,3,1]

Показывает просто и все дублирует и сохраняет порядок.

Ответ 14

Очень простой и быстрый способ поиска обмана с помощью одной итерации в Python:

testList = ['red', 'blue', 'red', 'green', 'blue', 'blue']

testListDict = {}

for item in testList:
  try:
    testListDict[item] += 1
  except:
    testListDict[item] = 1

print testListDict

Выход будет следующим:

>>> print testListDict
{'blue': 3, 'green': 1, 'red': 2}

Это и многое другое в моем блоге http://www.howtoprogramwithpython.com

Ответ 15

Мы можем использовать itertools.groupby, чтобы найти все предметы, у которых есть дубликаты:

from itertools import groupby

myList  = [2, 4, 6, 8, 4, 6, 12]
# when the list is sorted, groupby groups by consecutive elements which are similar
for x, y in groupby(sorted(myList)):
    #  list(y) returns all the occurences of item x
    if len(list(y)) > 1:
        print x  

Выход будет:

4
6

Ответ 16

list2 = [1, 2, 3, 4, 1, 2, 3]
lset = set()
[(lset.add(item), list2.append(item))
 for item in list2 if item not in lset]
print list(lset)

Ответ 17

Однострочное решение:

set([i for i in list if sum([1 for a in list if a == i]) > 1])

Ответ 18

Здесь много ответов, но я думаю, что это относительно понятный и понятный подход:

def get_duplicates(sorted_list):
    duplicates = []
    last = sorted_list[0]
    for x in sorted_list[1:]:
        if x == last:
            duplicates.append(x)
        last = x
    return set(duplicates)

Примечания:

  • Если вы хотите сохранить количество дубликатов, избавитесь от приведения "установить" внизу, чтобы получить полный список
  • Если вы предпочитаете использовать генераторы, замените duplicates.append(x) с помощью yield x и оператора return внизу (вы можете наложить его позже)

Ответ 19

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

Для списков со всеми элементами, которые являются хешируемыми типами:

def gen_dupes(array):
    unique = {}
    for value in array:
        if value in unique and unique[value]:
            unique[value] = False
            yield value
        else:
            unique[value] = True

array = [1, 2, 2, 3, 4, 1, 5, 2, 6, 6]
print(list(gen_dupes(array)))
# => [2, 1, 6]

Для списков, которые могут содержать списки:

def gen_dupes(array):
    unique = {}
    for value in array:
        is_list = False
        if type(value) is list:
            value = tuple(value)
            is_list = True

        if value in unique and unique[value]:
            unique[value] = False
            if is_list:
                value = list(value)

            yield value
        else:
            unique[value] = True

array = [1, 2, 2, [1, 2], 3, 4, [1, 2], 5, 2, 6, 6]
print(list(gen_dupes(array)))
# => [2, [1, 2], 6]

Ответ 20

def removeduplicates(a):
  seen = set()

  for i in a:
    if i not in seen:
      seen.add(i)
  return seen 

print(removeduplicates([1,1,2,2]))

Ответ 21

Некоторые другие тесты. Конечно, чтобы...

set([x for x in l if l.count(x) > 1])

... слишком дорого. Это примерно в 500 раз быстрее (чем длиннее массив дает лучшие результаты), чтобы использовать следующий окончательный метод:

def dups_count_dict(l):
    d = {}

    for item in l:
        if item not in d:
            d[item] = 0

        d[item] += 1

    result_d = {key: val for key, val in d.iteritems() if val > 1}

    return result_d.keys()

Только 2 l.count(), без очень дорогостоящих l.count().

Вот код для сравнения методов, например. Код ниже, вот вывод:

dups_count: 13.368s # this is a function which uses l.count()
dups_count_dict: 0.014s # this is a final best function (of the 3 functions)
dups_count_counter: 0.024s # collections.Counter

Код проверки:

import numpy as np
from time import time
from collections import Counter

class TimerCounter(object):
    def __init__(self):
        self._time_sum = 0

    def start(self):
        self.time = time()

    def stop(self):
        self._time_sum += time() - self.time

    def get_time_sum(self):
        return self._time_sum


def dups_count(l):
    return set([x for x in l if l.count(x) > 1])


def dups_count_dict(l):
    d = {}

    for item in l:
        if item not in d:
            d[item] = 0

        d[item] += 1

    result_d = {key: val for key, val in d.iteritems() if val > 1}

    return result_d.keys()


def dups_counter(l):
    counter = Counter(l)    

    result_d = {key: val for key, val in counter.iteritems() if val > 1}

    return result_d.keys()



def gen_array():
    np.random.seed(17)
    return list(np.random.randint(0, 5000, 10000))


def assert_equal_results(*results):
    primary_result = results[0]
    other_results = results[1:]

    for other_result in other_results:
        assert set(primary_result) == set(other_result) and len(primary_result) == len(other_result)


if __name__ == '__main__':
    dups_count_time = TimerCounter()
    dups_count_dict_time = TimerCounter()
    dups_count_counter = TimerCounter()

    l = gen_array()

    for i in range(3):
        dups_count_time.start()
        result1 = dups_count(l)
        dups_count_time.stop()

        dups_count_dict_time.start()
        result2 = dups_count_dict(l)
        dups_count_dict_time.stop()

        dups_count_counter.start()
        result3 = dups_counter(l)
        dups_count_counter.stop()

        assert_equal_results(result1, result2, result3)

    print 'dups_count: %.3f' % dups_count_time.get_time_sum()
    print 'dups_count_dict: %.3f' % dups_count_dict_time.get_time_sum()
    print 'dups_count_counter: %.3f' % dups_count_counter.get_time_sum()

Ответ 22

Способ 1:

list(set([val for idx, val in enumerate(input_list) if val in input_list[idx+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 метод name(), и он удаляет дубликаты,

Затем у нас остается набор, но не список, и, следовательно, для преобразования из набора в список мы используем typecasting, list(), и это преобразует набор элементов в список.

Способ 2:

def dupes(ilist):
    temp_list = [] # initially, empty temporary list
    dupe_list = [] # initially, empty duplicate list
    for each in ilist:
        if each in temp_list: # Found a Duplicate element
            if not each in dupe_list: # Avoid duplicate elements in dupe_list
                dupe_list.append(each) # Add duplicate element to dupe_list
        else: 
            temp_list.append(each) # Add a new (non-duplicate) to temp_list

    return dupe_list

Пояснение: Здесь мы создаем два пустых списка, для начала. Затем продолжайте просмотр всех элементов списка, чтобы увидеть, существует ли он в temp_list (изначально пустом). Если его нет в temp_list, мы добавляем его в temp_list, используя метод append.

Если он уже существует в temp_list, это означает, что текущий элемент списка является дубликатом, и, следовательно, нам нужно добавить его в dupe_list с помощью метода append.

Ответ 23

raw_list = [1,2,3,3,4,5,6,6,7,2,3,4,2,3,4,1,3,4,]

clean_list = list(set(raw_list))
duplicated_items = []

for item in raw_list:
    try:
        clean_list.remove(item)
    except ValueError:
        duplicated_items.append(item)


print(duplicated_items)
# [3, 6, 2, 3, 4, 2, 3, 4, 1, 3, 4]

Вы в основном удаляете дубликаты путем преобразования в set (clean_list), затем выполняете итерацию raw_list, удаляя каждый item в чистом списке для вхождения в raw_list. Если item не найден, ValueError исключение ValueError и item добавляется в список duplicated_items.

Если нужен индекс дублированных элементов, просто enumerate список и поиграйте с индексом. (for index, item in enumerate(raw_list): который быстрее и оптимизирован для больших списков (например, thousands+ элементов)

Ответ 24

использование метода list.count() в списке, чтобы найти дубликаты элементов данного списка

arr=[]
dup =[]
for i in range(int(input("Enter range of list: "))):
    arr.append(int(input("Enter Element in a list: ")))
for i in arr:
    if arr.count(i)>1 and i not in dup:
        dup.append(i)
print(dup)

Ответ 25

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

def dupList(oldlist):
    if type(oldlist)==type((2,2)):
        oldlist=[x for x in oldlist]
    newList=[]
    newList=newList+oldlist
    oldlist=oldlist
    forbidden=[]
    checkPoint=0
    for i in range(len(oldlist)):
        #print 'start i', i
        if i in forbidden:
            continue
        else:
            for j in range(len(oldlist)):
                #print 'start j', j
                if j in forbidden:
                    continue
                else:
                    #print 'after Else'
                    if i!=j: 
                        #print 'i,j', i,j
                        #print oldlist
                        #print newList
                        if oldlist[j]==oldlist[i]:
                            #print 'oldlist[i],oldlist[j]', oldlist[i],oldlist[j]
                            forbidden.append(j)
                            #print 'forbidden', forbidden
                            del newList[j-checkPoint]
                            #print newList
                            checkPoint=checkPoint+1
    return newList

поэтому ваш образец работает как:

>>>a = [1,2,3,3,3,4,5,6,6,7]
>>>dupList(a)
[1, 2, 3, 4, 5, 6, 7]

Ответ 26

При использовании toolz:

from toolz import frequencies, valfilter

a = [1,2,2,3,4,5,4]
>>> list(valfilter(lambda count: count > 1, frequencies(a)).keys())
[2,4] 

Ответ 27

Я вступаю намного позже в эту дискуссию. Хотя я бы хотел решить эту проблему с одним вкладышем. Потому что в этом прелесть Python. если мы просто хотим поместить дубликаты в отдельный список (или любую коллекцию), я бы предложил сделать это следующим образом. Скажем, у нас есть дублированный список, который мы можем назвать "целевым"

    target=[1,2,3,4,4,4,3,5,6,8,4,3]

Теперь, если мы хотим получить дубликаты, мы можем использовать один вкладыш, как показано ниже:

    duplicates=dict(set((x,target.count(x)) for x in filter(lambda rec : target.count(rec)>1,target)))

Этот код будет помещать дублированные записи в качестве ключа и считать как значение в словарь "дубликаты". "Дубликат" словарь будет выглядеть следующим образом:

    {3: 3, 4: 4} #it saying 3 is repeated 3 times and 4 is 4 times

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

    duplicates=filter(lambda rec : target.count(rec)>1,target)

Выход будет:

    [3, 4, 4, 4, 3, 4, 3]

Это прекрасно работает в версиях Python 2.7.x +

Ответ 28

одна строка, для удовольствия, и где требуется одно утверждение.

(lambda iterable: reduce(lambda (uniq, dup), item: (uniq, dup | {item}) if item in uniq else (uniq | {item}, dup), iterable, (set(), set())))(some_iterable)

Ответ 29

Я думаю, что наиболее эффективный способ найти дубликаты в списке:

from collection import Counter

def duplicates(values):
    dups = Counter(values) - Counter(set(values))
    return dups.keys()

Он использует Counter все элементы и все уникальные элементы. Вычитание первого со вторым исключит только дубликаты.

Ответ 30

Используйте функцию sort(). Дубликаты можно идентифицировать, перевернув его и проверив l1[i] == l1[i+1].