web-dev-qa-db-fra.com

Comment trouver les doublons dans une liste et créer une autre liste avec eux?

Comment trouver les doublons dans une liste Python et créer une autre liste des doublons? La liste ne contient que des entiers.

311
MFB

Pour supprimer les doublons, utilisez set(a). Pour imprimer des doublons, par exemple:

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]

Notez que Counter n’est pas particulièrement efficace ( timings ) et est probablement excessif ici. set fonctionnera mieux. Ce code calcule une liste d'éléments uniques dans l'ordre source:

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

ou plus simplement:

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

Je ne recommande pas ce dernier style, car ce que not seen.add(x) fait n'est pas évident (la méthode set add() renvoie toujours None, d'où la nécessité de not).

Pour calculer la liste des éléments dupliqués sans bibliothèques:

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

Si les éléments de la liste ne sont pas obligatoires, vous ne pouvez pas utiliser de sets/dicts et vous devez recourir à une solution temporelle quadratique (comparez-les chacun d’eux). Par exemple:

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]]
381
georg
>>> 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])
263
Ritesh Kumar

Vous n'avez pas besoin de compter, juste si l'élément a été vu auparavant. Adapté cette réponse à ce problème:

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]

Juste au cas où la vitesse importerait, voici quelques horaires:

# 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

Voici les résultats: (bravo @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

Fait intéressant, outre le minutage lui-même, le classement change également légèrement lorsque pypy est utilisé. Le plus intéressant est que l'approche basée sur Counter bénéficie énormément des optimisations de pypy, alors que l'approche de mise en cache de méthode que j'ai suggérée semble n'avoir presque aucun effet.

$ 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

Apparemment, cet effet est lié à la "duplication" des données d'entrée. J'ai mis l = [random.randrange(1000000) for i in xrange(10000)] et obtenu ces résultats:

$ 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
71
moooeeeep

Je suis tombé sur cette question en cherchant quelque chose de connexe - et je me suis demandé pourquoi personne ne proposait une solution basée sur un générateur? Résoudre ce problème serait:

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

Je m'inquiétais de l'évolutivité. J'ai donc testé plusieurs approches, y compris des éléments naïfs qui fonctionnent bien sur de petites listes, mais qui évoluent horriblement à mesure que les listes s'agrandissent (notez qu'il aurait été préférable d'utiliser timeit, mais c'est une illustration).

J'ai inclus @moooeeeep à des fins de comparaison (c'est impressionnant: rapide, si la liste d'entrée est complètement aléatoire) et une approche itertools encore plus rapide pour les listes généralement triées ... Inclut maintenant l'approche des pandas de @firelynx - lente, mais pas horriblement, et simple. Remarque: l'approche tri/départ/zip est systématiquement la plus rapide sur ma machine pour les grandes listes principalement ordonnées, moooeeeep est le plus rapide pour les listes mélangées, mais votre kilométrage peut varier.

Avantages

  • très rapide simple à tester pour "tout" les doublons en utilisant le même code

Hypothèses

  • Les doublons ne doivent être signalés qu'une seule fois
  • Les commandes en double n'ont pas besoin d'être conservées
  • Les doublons peuvent être n'importe où dans la liste

La solution la plus rapide, 1 million d'entrées:

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

Approches testées

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

Les résultats du test 'tous les dupes' étaient cohérents, en trouvant les doublons "d'abord" puis "tous" en double dans ce tableau:

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  

Lorsque les listes sont mélangées en premier, le prix de la sorte devient évident - l'efficacité diminue nettement et l'approche @moooeeeep domine, les approches set & dict étant similaires, mais les moins performants:

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  
27
F1Rumors

Vous pouvez utiliser iteration_utilities.duplicates :

>>> from iteration_utilities import duplicates

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

ou si vous ne voulez qu'un seul de ces doublons, vous pouvez le combiner avec iteration_utilities.unique_everseen :

>>> from iteration_utilities import unique_everseen

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

Il peut également gérer des éléments insaisissables (mais au détriment des performances):

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

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

C’est quelque chose que seules quelques-unes des autres approches peuvent gérer.

Des repères

J'ai fait un repère rapide contenant la plupart (mais pas toutes) des approches mentionnées ici.

Le premier point de référence n'incluait qu'un petit nombre de longueurs de liste car certaines approches ont un comportement O(n**2).

Dans les graphiques, l'axe des y représente le temps, donc une valeur inférieure signifie mieux. Il est également tracé log-log afin de mieux visualiser le large éventail de valeurs:

 enter image description here

En supprimant les approches O(n**2), j’ai réalisé un autre point de repère jusqu’à un demi million d’éléments dans une liste:

 enter image description here

Comme vous pouvez le constater, l’approche iteration_utilities.duplicates est plus rapide que n’importe laquelle des autres approches et même l’enchaînement de unique_everseen(duplicates(...)) était plus rapide ou aussi rapide que les autres.

Une autre chose intéressante à noter ici est que les approches de pandas sont très lentes pour les petites listes mais peuvent facilement rivaliser pour des listes plus longues.

Cependant, comme ces repères montrent que la plupart des approches fonctionnent à peu près également, il est donc inutile d’utiliser celle qui est utilisée (à l’exception des 3 qui avaient O(n**2) runtime). 

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)))

Benchmark 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()

Benchmark 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()

Avertissement

1 Ceci provient d'une bibliothèque tierce que j'ai écrite: iteration_utilities .

19
MSeifert

collections.Counter est une nouveauté de 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'
>>>

Dans une version antérieure, vous pouvez utiliser un dict conventionnel à la place:

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]
11
Edward

À l'aide de 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])
10
wordsmith

Voici une solution soignée et concise -

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

li = list(set(li))
7
Nikhil Prabhu

Sans convertir en liste et probablement la manière la plus simple serait comme ci-dessous . Cela peut être utile pendant une interview quand ils demandent de ne pas utiliser de sets

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

======= sinon pour obtenir 2 listes séparées de valeurs uniques et de valeurs en double

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)
6
Chetan Vasudevan

Pourquoi ne pas simplement parcourir chaque élément de la liste en vérifiant le nombre d’occurrences, puis en les ajoutant à un ensemble qui imprimera ensuite les doublons J'espère que cela aide quelqu'un là-bas.

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]
6
HenryDev

Je le ferais avec des pandas, car j'utilise beaucoup de 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()

Donne

[3,6]

Ce n’est probablement pas très efficace, mais c’est moins de code que beaucoup d’autres réponses, j’ai donc pensé contribuer

5
firelynx

le troisième exemple de réponse acceptée donne une réponse erronée et n'essaie pas de donner des doublons. Voici la version correcte:

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
5
yota

Un peu en retard, mais peut-être utile pour certains …………….

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]

Montre juste et tous les doublons et préserve l'ordre.

4
user3109122

Voici un moyen très simple et rapide de rechercher des dupes avec une seule itération en Python:

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

testListDict = {}

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

print testListDict

La sortie sera comme suit:

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

Ceci et plus dans mon blog http://www.howtoprogramwithpython.com

3
Igor Vishnevskiy

Nous pouvons utiliser itertools.groupby afin de trouver tous les articles qui ont des doublons:

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  

La sortie sera:

4
6
3
alfasin

Il y a beaucoup de réponses ici, mais je pense que c'est une approche relativement très lisible et facile à comprendre:

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)

Remarques:

  • Si vous souhaitez conserver le nombre de doublons, supprimez la distributionPour 'définir' en bas pour obtenir la liste complète
  • Si vous préférez utiliser des générateurs, remplacez duplicates.append (x) par yield x et la déclaration de retour située au bas de la page (vous pouvez lancer la conversion pour définir ultérieurement).
1
tvt173

Voici un générateur rapide qui utilise un dict pour stocker chaque élément en tant que clé avec une valeur booléenne pour vérifier si l'élément en double a déjà été généré.

Pour les listes avec tous les éléments qui sont des types hashable:

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]

Pour les listes pouvant contenir des listes:

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]
1
John B

Quelques autres tests. Bien sur à faire ...

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

... est trop coûteux. Utiliser la méthode finale suivante est environ 500 fois plus rapide (le tableau le plus long donne de meilleurs résultats)

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()

Seulement 2 boucles, pas d'opération l.count() très coûteuse.

Voici un code pour comparer les méthodes par exemple. Le code est ci-dessous, voici la sortie:

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

Le code de test:

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 __== '__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()
1
sergzach
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]

Vous supprimez essentiellement les doublons en convertissant la valeur en (clean_list), puis en itérant le raw_list, tout en supprimant chaque item de la liste de nettoyage pour l'occurrence dans raw_list. Si item n'est pas trouvé, l'exception ValueError déclenchée est interceptée et la item est ajoutée à la liste duplicated_items.

Si l'index des éléments dupliqués est nécessaire, il suffit de enumerate la liste et de jouer avec l'index. (for index, item in enumerate(raw_list):) qui est plus rapide et optimisé pour les listes volumineuses (comme des milliers d'éléments)

1

Une solution en ligne:

set([i for i in list if sum([1 for a in list if a == i]) > 1])
1
ytpillai
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)
1
Haresh Shyara
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]))
1
ASHISH RANJAN

Méthode 1:

list(set([val for idx, val in enumerate(input_list) if val in input_list[idx+1:]]))

Explication: [Val pour idx, val dans enumerate (input_list) si val dans input_list [idx + 1:]] est une liste à comprendre, qui retourne un élément, si le même élément est présent depuis sa valeur actuelle position, dans la liste, l'index.

Exemple: Input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]

en commençant par le premier élément de la liste, 42, avec l'index 0, il vérifie si l'élément 42 est présent dans input_list [1:] (c'est-à-dire, de l'index 1 à la fin de la liste) Parce que 42 est présent dans input_list [ 1:], il reviendra 42.

Ensuite, il passe à l'élément suivant 31, avec l'index 1, et vérifie si l'élément 31 est présent dans la input_list [2:] (c'est-à-dire, de l'index 2 à la fin de la liste), .__, car 31 est présent dans input_list [2 :], il retournera le 31.

de même, il parcourt tous les éléments de la liste et ne renvoie que les éléments répétés/dupliqués dans une liste.

Ensuite, parce que nous avons des doublons, dans une liste, nous devons en choisir un, c’est-à-dire supprimer les doublons parmi les doublons, et pour ce faire, nous appelons un ensemble python nommé nommé (), qui supprime les doublons.

Ensuite, il nous reste un ensemble, mais pas une liste, et donc pour convertir un ensemble en liste, nous utilisons, typecasting, list (), et cela convertit l'ensemble des éléments en liste.

Méthode 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

Explication: Ici, nous créons deux listes vides, pour commencer par . Continuez ensuite à parcourir tous les éléments de la liste pour voir si elle existe dans temp_list (initialement vide). S'il ne figure pas dans la liste temp_list, nous l'ajoutons à la liste temp_list à l'aide de la méthode append.

S'il existe déjà dans temp_list, cela signifie que l'élément actuel de la liste est un doublon et nous devons donc l'ajouter à dupe_list en utilisant la méthode append.

0
Sundeep Borra

J'entre beaucoup beaucoup tard dans cette discussion. Même si, je voudrais traiter ce problème avec un liners. Parce que c’est le charme de Python . Si nous voulons seulement obtenir les doublons dans une liste séparée (ou n’importe quelle collection), je suggérerais de faire comme ci-dessous. Disons que nous avons une liste dupliquée que nous pouvons appeler '

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

Maintenant, si nous voulons obtenir les doublons, nous pouvons utiliser la doublure suivante:

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

Ce code mettra les enregistrements dupliqués comme clé et comptera comme valeur dans le dictionnaire 'duplicates'. Le dictionnaire 'duplicate' ressemblera à celui ci-dessous:

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

Si vous voulez juste que tous les enregistrements avec des doublons soient seuls dans une liste, son code est beaucoup plus court:

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

La sortie sera:

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

Cela fonctionne parfaitement dans les versions python 2.7.x +

0

c'est comme ça que je devais le faire parce que je me suis mis au défi de ne pas utiliser d'autres méthodes:

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

si votre échantillon fonctionne comme:

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

utilisation de la méthode list.count() dans la liste pour trouver les éléments en double d'une liste donnée

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)
0
Ravikiran D

Lorsque vous utilisez 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] 
0
Andreas Profous