Comment puis-je trouver les doublons dans une liste Python et créer une autre liste des doublons? La liste ne contient que des entiers.
Comment puis-je trouver les doublons dans une liste Python et créer une autre liste des doublons? La liste ne contient que des entiers.
Réponses:
Pour supprimer les doublons, utilisez set(a)
. Pour imprimer des doublons, quelque chose comme:
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 ce Counter
n'est pas particulièrement efficace ( timings ) et probablement exagéré 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 concis:
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 n'est pas évident not seen.add(x)
(la add()
méthode set revient toujours None
, d'où la nécessité 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 hachables, vous ne pouvez pas utiliser d'ensembles / dict et devez recourir à une solution temporelle quadratique (comparer chacun avec chacun). 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]]
O(n)
, car il n'itère la liste qu'une seule fois et les recherches définies le sont O(1)
.
dup = []
else: dup.append(x)
print()
seen = set()
puisdupe = set(x for x in a if x in seen or seen.add(x))
>>> 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])
l
par set(l)
ne réduit que la complexité temporelle la plus défavorable et ne fait donc rien pour résoudre les problèmes d'efficacité à plus grande échelle avec cette réponse. Ce n'était probablement pas si simple après tout. Bref, ne faites pas ça.
Vous n'avez pas besoin du nombre, juste si l'article a été vu auparavant ou non. 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 compte, voici quelques timings:
# 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 timing lui-même, le classement change également légèrement lorsque Pypy est utilisé. Plus intéressant encore, l'approche Counter-based bénéficie énormément des optimisations de Pypy, tandis 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 défini 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
add
chaque fois qu'une insertion sera nécessaire.
pypy
si vous l'avez à portée de main et que vous allez pour la vitesse.
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 chaque doublon, cela peut être combiné 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 non lavables (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 ici peuvent gérer.
J'ai fait un benchmark rapide contenant la plupart (mais pas toutes) des approches mentionnées ici.
Le premier repère ne comprenait qu'une petite gamme de longueurs de liste car certaines approches O(n**2)
comportement.
Dans les graphiques, l'axe des y représente le temps, donc une valeur inférieure signifie mieux. Il est également tracé le journal de bord afin que la large gamme de valeurs puisse être mieux visualisée:
En supprimant les O(n**2)
approches, j'ai fait un autre benchmark jusqu'à un demi-million d'éléments dans une liste:
Comme vous pouvez le voir, l' iteration_utilities.duplicates
approche est plus rapide que toutes les autres approches et même le chaînage unique_everseen(duplicates(...))
était plus rapide ou aussi rapide que les autres approches.
Une autre chose intéressante à noter ici est que les approches des pandas sont très lentes pour les petites listes mais peuvent facilement rivaliser pour les listes plus longues.
Cependant, comme ces tests de référence montrent que la plupart des approches fonctionnent à peu près de la même manière, peu importe laquelle est utilisée (à l'exception des 3 qui avaient un O(n**2)
temps d'exécution).
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)))
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()
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 Ceci est d'une bibliothèque tierce , je l' ai écrit: iteration_utilities
.
Je suis tombé sur cette question en regardant quelque chose de connexe - et je me demande pourquoi personne n'a offert 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]
J'étais préoccupé par l'évolutivité, j'ai donc testé plusieurs approches, y compris des éléments naïfs qui fonctionnent bien sur de petites listes, mais évoluent horriblement à mesure que les listes s'agrandissent (note - il aurait été préférable d'utiliser timeit, mais cela est illustratif).
J'ai inclus @moooeeeep pour comparaison (c'est incroyablement rapide: plus rapide si la liste d'entrée est complètement aléatoire) et une approche itertools qui est encore plus rapide pour les listes principalement triées ... Inclut maintenant l'approche pandas de @firelynx - lente, mais pas horriblement et simple. Remarque - l'approche tri / tee / zip est toujours la plus rapide sur ma machine pour les grandes listes principalement commandées, moooeeeep est la plus rapide pour les listes mélangées, mais votre kilométrage peut varier.
Les avantages
Hypothèses
Solution la plus rapide, 1m 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 pour le test «toutes les dupes» étaient cohérents, trouvant «premier» doublon puis «tous» les doublons 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 du tri devient apparent - l'efficacité chute sensiblement et l'approche @moooeeeep domine, les approches set & dict étant similaires mais moins performantes:
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
random.shuffle(c)
en tenir compte. De plus, je ne peux pas non plus répliquer vos résultats lors de l'exécution du script non modifié (ordre totalement différent), donc cela dépend peut-être aussi du CPU.
collections.Counter est nouveau en 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 classique à 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]
Voici une solution nette et concise -
for x in set(li):
li.remove(x)
li = list(set(li))
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 certainement moins de code que la plupart des autres réponses, alors j'ai pensé contribuer
pda = pd.Series(a)
print list(pda[pda.duplicated()])
Sans convertir en liste et probablement le moyen le plus simple serait quelque chose comme ci-dessous. Cela peut être utile lors d'un entretien quand ils demandent de ne pas utiliser d'ensembles
a=[1,2,3,3,3]
dup=[]
for each in a:
if each not in dup:
dup.append(each)
print(dup)
======= else pour obtenir 2 listes distinctes 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)
le troisième exemple de la réponse acceptée donne une réponse erronée et n'essaie pas de donner des doublons. Voici la bonne version:
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
Que diriez-vous simplement de 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]
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
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Je suppose que le moyen le plus efficace de trouver des doublons dans une liste est:
from collections import Counter
def duplicates(values):
dups = Counter(values) - Counter(set(values))
return list(dups.keys())
print(duplicates([1,2,3,6,5,2]))
Il utilise Counter
tous les éléments et tous les éléments uniques. Soustraire le premier au second ne laissera de côté que les doublons.
Un peu tard, mais peut-être utile pour certains. Pour une liste assez longue, j'ai trouvé que cela fonctionnait pour moi.
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]
Affiche juste et tous les doublons et préserve l'ordre.
Un moyen très simple et rapide de trouver des dupes avec une seule itération en Python est:
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 la suivante:
>>> print testListDict
{'blue': 3, 'green': 1, 'red': 2}
Ceci et plus dans mon blog http://www.howtoprogramwithpython.com
J'entre beaucoup plus 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 simplement obtenir les doublons dans une liste séparée (ou n'importe quelle collection), je suggère de faire comme ci-dessous. Dites que nous avons une liste dupliquée que nous pouvons appeler comme `` cible ''
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 comme ci-dessous:
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 à ce qui suit:
{3: 3, 4: 4} #it saying 3 is repeated 3 times and 4 is 4 times
Si vous voulez juste tous les enregistrements avec des doublons seuls dans une liste, son code est encore 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 +
Python 3.8 one-liner si vous ne vous souciez pas d'écrire votre propre algorithme ou d'utiliser des bibliothèques:
l = [1,2,3,2,1,5,6,5,5,5]
res = [(x, count) for x, g in groupby(sorted(l)) if (count := len(list(g))) > 1]
print(res)
Imprime l'élément et compte:
[(1, 2), (2, 2), (5, 4)]
groupby
prend une fonction de regroupement afin que vous puissiez définir vos regroupements de différentes manières et renvoyer des informations supplémentaires Tuple
champs si nécessaire.
groupby
est paresseux donc ça ne devrait pas être trop lent.
Quelques autres tests. Bien sûr à faire ...
set([x for x in l if l.count(x) > 1])
... est trop coûteux. C'est environ 500 fois plus rapide (le tableau le plus long donne de meilleurs résultats) pour utiliser la méthode finale suivante:
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 très coûteuses l.count()
opérations .
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 __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()
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 en énumération (liste_entrée) si val dans liste_entrée [idx + 1:]] est une compréhension de liste, qui renvoie un élément, si le même élément est présent à partir de sa position actuelle, dans la liste, l'index .
Exemple: liste_entrées = [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 jusqu'à la fin de la liste) Parce que 42 est présent dans input_list [1:] , il retournera 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 liste_entrée [2:] (c'est-à-dire de l'index 2 jusqu'à la fin de la liste), Parce que 31 est présent dans la liste_entrée [2:], il reviendra 31.
de même, il parcourt tous les éléments de la liste et ne renvoie que les éléments répétés / en double dans une liste.
Ensuite, parce que nous avons des doublons, dans une liste, nous devons choisir un de chaque doublon, c'est-à-dire supprimer le doublon parmi les doublons, et pour ce faire, nous appelons un ensemble nommé python nommé set (), et il supprime les doublons,
Ensuite, nous nous retrouvons avec un ensemble, mais pas une liste, et donc pour convertir d'un ensemble en liste, nous utilisons, le transtypage, list (), et qui convertit l'ensemble des éléments en une 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. Continuez ensuite à parcourir tous les éléments de la liste, pour voir si elle existe dans temp_list (initialement vide). S'il n'est pas là dans la temp_list, alors nous l'ajoutons à la temp_list, en utilisant la méthode append .
S'il existe déjà dans temp_list, cela signifie que l'élément courant de la liste est un doublon, et donc nous devons l'ajouter à dupe_list en utilisant la méthode append .
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 les convertissant en set ( clean_list
), puis en itérant le raw_list
, tout en supprimant chacun item
dans la liste claire pour l'occurrence dans raw_list
. S'il item
n'est pas trouvé, l' ValueError
exception déclenchée est interceptée et item
ajoutée à la duplicated_items
liste.
Si l'index des éléments dupliqués est nécessaire, juste enumerate
la liste et jouer avec l'index. ( for index, item in enumerate(raw_list):
) qui est plus rapide et optimisé pour les grandes listes (comme des milliers + d'éléments)
utilisation d'une list.count()
méthode 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)
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)
Il y a beaucoup de réponses ici, mais je pense que c'est relativement une approche 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:
Voici un générateur rapide qui utilise un dict pour stocker chaque élément sous forme de 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 hachables:
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]
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]))
Lors de l'utilisation de 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]
c'est ainsi que je devais le faire car 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
pour que votre échantillon fonctionne comme:
>>>a = [1,2,3,3,3,4,5,6,6,7]
>>>dupList(a)
[1, 2, 3, 4, 5, 6, 7]
duplist = list(set(a))
.