Wie kann ich die Duplikate in einer Python-Liste finden und eine weitere Liste der Duplikate erstellen? Die Liste enthält nur Ganzzahlen.
Wie kann ich die Duplikate in einer Python-Liste finden und eine weitere Liste der Duplikate erstellen? Die Liste enthält nur Ganzzahlen.
Antworten:
Verwenden Sie zum Entfernen von Duplikaten set(a)
. So drucken Sie Duplikate:
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]
Beachten Sie, dass dies Counter
nicht besonders effizient ist ( Timings ) und hier wahrscheinlich übertrieben ist. set
wird besser abschneiden. Dieser Code berechnet eine Liste eindeutiger Elemente in der Quellreihenfolge:
seen = set()
uniq = []
for x in a:
if x not in seen:
uniq.append(x)
seen.add(x)
oder genauer:
seen = set()
uniq = [x for x in a if x not in seen and not seen.add(x)]
Ich empfehle den letzteren Stil nicht, da nicht klar ist, was er not seen.add(x)
tut (die set- add()
Methode gibt immer zurück None
, daher ist dies erforderlichnot
).
So berechnen Sie die Liste der duplizierten Elemente ohne Bibliotheken:
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
Wenn Listenelemente nicht hashbar sind, können Sie keine Mengen / Diktate verwenden und müssen auf eine quadratische Zeitlösung zurückgreifen (vergleichen Sie jede mit jeder). Zum Beispiel:
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)
, weil es die Liste nur einmal wiederholt und Set-Lookups sind O(1)
.
dup = []
else: dup.append(x)
print()
seen = set()
danndupe = 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
mit set(l)
nur reduziert die Worst-Case - Zeitkomplexität und damit nicht nichts mit dieser Antwort , die größere Effizienz Bedenken auszuräumen. Es war wahrscheinlich doch nicht so einfach. Kurz gesagt, tu das nicht.
Sie brauchen die Zählung nicht, nur ob der Gegenstand zuvor gesehen wurde oder nicht. Diese Antwort wurde an dieses Problem angepasst :
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]
Nur für den Fall, dass Geschwindigkeit wichtig ist, hier einige Zeitpunkte:
# 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
Hier sind die Ergebnisse: (gut gemacht @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
Interessanterweise ändert sich neben den Timings selbst auch das Ranking geringfügig, wenn Pypy verwendet wird. Am interessantesten ist, dass der Counter-basierte Ansatz enorm von den Optimierungen von pypy profitiert, während der von mir vorgeschlagene Methoden-Caching-Ansatz fast keine Wirkung zu haben scheint.
$ 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
Anscheinend hängt dieser Effekt mit der "Duplizierung" der Eingabedaten zusammen. Ich habe l = [random.randrange(1000000) for i in xrange(10000)]
diese Ergebnisse festgelegt und erhalten:
$ 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
jedes Mal nachschlagen (eine Wörterbuchabfrage), wenn eine Einfügung erforderlich wäre.
pypy
Sie es auch, wenn Sie es zur Hand haben und Geschwindigkeit anstreben .
Sie können verwenden iteration_utilities.duplicates
:
>>> from iteration_utilities import duplicates
>>> list(duplicates([1,1,2,1,2,3,4,2]))
[1, 1, 2, 2]
oder wenn Sie nur eines von jedem Duplikat möchten, kann dies kombiniert werden mit iteration_utilities.unique_everseen
:
>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen(duplicates([1,1,2,1,2,3,4,2])))
[1, 2]
Es kann auch nicht zerhackbare Elemente verarbeiten (jedoch auf Kosten der Leistung):
>>> list(duplicates([[1], [2], [1], [3], [1]]))
[[1], [1]]
>>> list(unique_everseen(duplicates([[1], [2], [1], [3], [1]])))
[[1]]
Das ist etwas, das nur einige der anderen Ansätze hier bewältigen können.
Ich habe einen schnellen Benchmark durchgeführt, der die meisten (aber nicht alle) der hier genannten Ansätze enthält.
Der erste Benchmark umfasste nur einen kleinen Bereich von Listenlängen, da einige Ansätze dies getan haben O(n**2)
Verhalten aufweisen.
In den Diagrammen stellt die y-Achse die Zeit dar, daher bedeutet ein niedrigerer Wert besser. Es wird auch ein Protokoll-Protokoll aufgezeichnet, damit der breite Wertebereich besser visualisiert werden kann:
Entfernen der O(n**2)
Ansätze Ich habe einen weiteren Benchmark mit bis zu einer halben Million Elementen in einer Liste durchgeführt:
Wie Sie sehen können, ist der iteration_utilities.duplicates
Ansatz schneller als jeder andere Ansatz und sogar verkettetunique_everseen(duplicates(...))
war schneller oder gleich schnell als die anderen Ansätze.
Eine weitere interessante Sache, die hier zu beachten ist, ist, dass die Pandas-Ansätze für kleine Listen sehr langsam sind, aber leicht für längere Listen konkurrieren können.
Da diese Benchmarks jedoch zeigen, dass die meisten Ansätze ungefähr gleich gut abschneiden, spielt es keine Rolle, welcher verwendet wird (mit Ausnahme der 3, die O(n**2)
Laufzeit hatten).
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 Dies ist aus einer Drittanbieter-Bibliothek, die ich geschrieben habe : iteration_utilities
.
Ich bin auf diese Frage gestoßen, als ich mich mit etwas Ähnlichem befasst habe - und habe mich gefragt, warum niemand eine generatorbasierte Lösung angeboten hat? Die Lösung dieses Problems wäre:
>>> print list(getDupes_9([1,2,3,2,1,5,6,5,5,5]))
[1, 2, 5]
Ich befasste mich mit der Skalierbarkeit und testete daher verschiedene Ansätze, einschließlich naiver Elemente, die auf kleinen Listen gut funktionieren, aber schrecklich skalieren, wenn Listen größer werden (Hinweis: Es wäre besser gewesen, timeit zu verwenden, aber dies ist illustrativ).
Ich habe @moooeeeep zum Vergleich hinzugefügt (es ist beeindruckend schnell: am schnellsten, wenn die Eingabeliste völlig zufällig ist) und einen itertools-Ansatz, der für meist sortierte Listen noch schneller ist ... Enthält jetzt den Pandas-Ansatz von @firelynx - langsam, aber nicht schrecklich und einfach. Hinweis - Der Sortier- / Abschlag- / Zip-Ansatz ist auf meinem Computer für große, meist geordnete Listen durchweg am schnellsten. Für gemischte Listen ist moooeeeep am schnellsten, aber Ihr Kilometerstand kann variieren.
Vorteile
Annahmen
Schnellste Lösung, 1m Einträge:
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
Ansätze getestet
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
Die Ergebnisse für den Test "Alle Dupes" waren konsistent und ergaben "zuerst" Duplikate, dann "alle" Duplikate in diesem Array:
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
Wenn die Listen zuerst gemischt werden, wird der Preis der Sortierung offensichtlich - die Effizienz sinkt merklich und der @ moooeeeep-Ansatz dominiert, wobei Set & Dict-Ansätze ähnlich sind, aber weniger Leistungsträger sind:
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)
das berücksichtigen. Außerdem kann ich Ihre Ergebnisse auch beim Ausführen des unveränderten Skripts nicht replizieren (völlig andere Reihenfolge), sodass dies möglicherweise auch von der CPU abhängt.
Pandas benutzen:
>>> import pandas as pd
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> pd.Series(a)[pd.Series(a).duplicated()].values
array([1, 3, 3])
Sammlungen.Counter ist neu in 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'
>>>
In einer früheren Version können Sie stattdessen ein herkömmliches Diktat verwenden:
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]
Hier ist eine saubere und prägnante Lösung -
for x in set(li):
li.remove(x)
li = list(set(li))
Ohne Konvertierung in eine Liste und wahrscheinlich der einfachste Weg wäre so etwas wie unten. Dies kann während eines Interviews nützlich sein, wenn sie darum bitten, keine Sets zu verwenden
a=[1,2,3,3,3]
dup=[]
for each in a:
if each not in dup:
dup.append(each)
print(dup)
======= sonst, um 2 separate Listen mit eindeutigen Werten und doppelten Werten zu erhalten
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)
Ich würde das mit Pandas machen, weil ich viel Pandas benutze
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()
Gibt
[3,6]
Wahrscheinlich ist es nicht sehr effizient, aber es ist sicher weniger Code als viele andere Antworten, also dachte ich, ich würde dazu beitragen
pda = pd.Series(a)
print list(pda[pda.duplicated()])
Das dritte Beispiel der akzeptierten Antwort gibt eine fehlerhafte Antwort und versucht nicht, Duplikate zu geben. Hier ist die richtige 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
Wie wäre es, wenn Sie einfach jedes Element in der Liste durchlaufen, indem Sie die Anzahl der Vorkommen überprüfen und sie dann einem Satz hinzufügen, der dann die Duplikate druckt. Hoffe das hilft jemandem da draußen.
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]
Wir können verwenden itertools.groupby
, um alle Gegenstände zu finden, die Dups haben:
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
Die Ausgabe wird sein:
4
6
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Ich denke, der effektivste Weg, um Duplikate in einer Liste zu finden, ist:
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]))
Es werden Counter
alle Elemente und alle eindeutigen Elemente verwendet. Wenn Sie das erste vom zweiten subtrahieren, werden nur die Duplikate weggelassen.
Ein bisschen spät, aber vielleicht hilfreich für einige. Für eine größere Liste fand ich, dass dies für mich funktionierte.
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]
Zeigt nur und alle Duplikate und behält die Ordnung bei.
Eine sehr einfache und schnelle Möglichkeit, Dupes mit einer Iteration in Python zu finden, ist:
testList = ['red', 'blue', 'red', 'green', 'blue', 'blue']
testListDict = {}
for item in testList:
try:
testListDict[item] += 1
except:
testListDict[item] = 1
print testListDict
Die Ausgabe erfolgt wie folgt:
>>> print testListDict
{'blue': 3, 'green': 1, 'red': 2}
Dies und mehr in meinem Blog http://www.howtoprogramwithpython.com
Ich komme viel zu spät in diese Diskussion. Auch wenn ich dieses Problem gerne mit einem Liner behandeln möchte. Denn das ist der Reiz von Python. Wenn wir nur die Duplikate in eine separate Liste (oder eine beliebige Sammlung) aufnehmen möchten, würde ich Folgendes vorschlagen. Wir haben eine doppelte Liste, die wir als "Ziel" bezeichnen können.
target=[1,2,3,4,4,4,3,5,6,8,4,3]
Wenn wir nun die Duplikate erhalten möchten, können wir den einen Liner wie folgt verwenden:
duplicates=dict(set((x,target.count(x)) for x in filter(lambda rec : target.count(rec)>1,target)))
Dieser Code fügt die duplizierten Datensätze als Schlüssel ein und zählt als Wert in das Wörterbuch "Duplikate". Das Wörterbuch "Duplikate" sieht wie folgt aus:
{3: 3, 4: 4} #it saying 3 is repeated 3 times and 4 is 4 times
Wenn Sie nur alle Datensätze mit Duplikaten in einer Liste haben möchten, ist der Code wieder viel kürzer:
duplicates=filter(lambda rec : target.count(rec)>1,target)
Ausgabe wird sein:
[3, 4, 4, 4, 3, 4, 3]
Dies funktioniert perfekt in Python 2.7.x + Versionen
Python 3.8 Einzeiler, wenn Sie keinen eigenen Algorithmus schreiben oder Bibliotheken verwenden möchten:
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)
Druckt Artikel und Anzahl:
[(1, 2), (2, 2), (5, 4)]
groupby
übernimmt eine Gruppierungsfunktion, sodass Sie Ihre Gruppierungen auf unterschiedliche Weise definieren und Tuple
bei Bedarf zusätzliche Felder zurückgeben können.
groupby
ist faul, also sollte es nicht zu langsam sein.
Einige andere Tests. Natürlich zu tun ...
set([x for x in l if l.count(x) > 1])
... ist zu teuer. Die nächste endgültige Methode ist ungefähr 500-mal schneller (je länger das Array, desto bessere Ergebnisse):
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()
Nur 2 Schleifen, keine sehr kostspieligen l.count()
Operationen.
Hier ist ein Code zum Vergleichen der Methoden zum Beispiel. Der Code ist unten, hier ist die Ausgabe:
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
Der Testcode:
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()
Methode 1:
list(set([val for idx, val in enumerate(input_list) if val in input_list[idx+1:]]))
Erläuterung: [val für idx, val in enumerate (input_list), wenn val in input_list [idx + 1:]] ein Listenverständnis ist, das ein Element zurückgibt, wenn dasselbe Element von seiner aktuellen Position in list, dem Index, vorhanden ist .
Beispiel: input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
Beginnend mit dem ersten Element in der Liste 42 mit dem Index 0 wird geprüft, ob das Element 42 in der Eingabeliste [1:] vorhanden ist (dh von Index 1 bis zum Ende der Liste), da 42 in der Eingabeliste [1:] vorhanden ist. wird es 42 zurückgeben.
Dann geht es zum nächsten Element 31 mit Index 1 und prüft, ob Element 31 in der Eingabeliste [2:] vorhanden ist (dh von Index 2 bis zum Ende der Liste), da 31 in Eingabeliste [2:] vorhanden ist. es wird 31 zurückgeben.
In ähnlicher Weise werden alle Elemente in der Liste durchlaufen und nur die wiederholten / doppelten Elemente in eine Liste zurückgegeben.
Da wir dann Duplikate in einer Liste haben, müssen wir eines von jedem Duplikat auswählen, dh Duplikate unter Duplikaten entfernen. Dazu rufen wir ein in Python eingebautes namens set () auf und es entfernt die Duplikate.
Dann bleibt uns eine Menge übrig, aber keine Liste. Um von einer Menge in eine Liste zu konvertieren, verwenden wir typecasting, list () und konvertieren die Menge der Elemente in eine Liste.
Methode 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
Erläuterung: Hier erstellen wir zunächst zwei leere Listen. Durchlaufen Sie dann alle Elemente der Liste, um festzustellen, ob sie in temp_list vorhanden sind (anfangs leer). Wenn es nicht in der temp_list vorhanden ist, fügen wir es mithilfe der append- Methode zur temp_list hinzu .
Wenn es bereits in temp_list vorhanden ist, bedeutet dies, dass das aktuelle Element der Liste ein Duplikat ist. Daher müssen wir es mit der Methode append zu dupe_list hinzufügen .
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]
Sie entfernen Duplikate im Grunde genommen, indem Sie sie in set ( clean_list
) konvertieren und dann die iterieren raw_list
, während Sie jedes item
in der Bereinigungsliste für das Auftreten in entfernen raw_list
. Wird dies item
nicht gefunden, wird die ausgelöste ValueError
Ausnahme abgefangen und item
zur duplicated_items
Liste hinzugefügt .
Wenn der Index der duplizierten Elemente benötigt wird, nur enumerate
die Liste und spielen Sie mit dem Index herum. ( for index, item in enumerate(raw_list):
) ist schneller und optimiert für große Listen (wie Tausende von Elementen)
Verwendung der list.count()
Methode in der Liste, um die doppelten Elemente einer bestimmten Liste herauszufinden
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)
Hier oben gibt es viele Antworten, aber ich denke, dies ist ein relativ gut lesbarer und leicht verständlicher Ansatz:
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)
Anmerkungen:
Hier ist ein schneller Generator, der ein Diktat verwendet, um jedes Element als Schlüssel mit einem booleschen Wert zu speichern, um zu überprüfen, ob das doppelte Element bereits ausgegeben wurde.
Für Listen mit allen Elementen, die Hash-Typen sind:
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]
Für Listen, die möglicherweise Listen enthalten:
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]))
Bei Verwendung von 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]
So musste ich es machen, weil ich mich herausforderte, keine anderen Methoden anzuwenden:
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
Ihre Probe funktioniert also wie folgt:
>>>a = [1,2,3,3,3,4,5,6,6,7]
>>>dupList(a)
[1, 2, 3, 4, 5, 6, 7]
duplist = list(set(a))
.