Ich muss so ziemlich ein Programm schreiben, um zu überprüfen, ob eine Liste Duplikate enthält, und wenn dies der Fall ist, werden diese entfernt und eine neue Liste mit den Elementen zurückgegeben, die nicht dupliziert / entfernt wurden. Das habe ich, aber um ehrlich zu sein, weiß ich nicht, was ich tun soll.
def remove_duplicates():
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
for t in t2:
t.append(t.remove())
return t
python
algorithm
list
duplicates
intersection
Neemaximo
quelle
quelle
Antworten:
Der übliche Ansatz, um eine eindeutige Sammlung von Elementen zu erhalten, ist die Verwendung von a
set
. Sets sind ungeordnete Sammlungen unterschiedlicher Objekte. Um einen Satz aus einem beliebigen Iterable zu erstellen, können Sie ihn einfach an die integrierteset()
Funktion übergeben. Wenn Sie später wieder eine echte Liste benötigen, können Sie den Satz ebenfalls an dielist()
Funktion übergeben.Das folgende Beispiel sollte alles abdecken, was Sie versuchen:
Wie Sie dem Beispielergebnis entnehmen können, wird die ursprüngliche Reihenfolge nicht beibehalten . Wie oben erwähnt, sind Sets selbst ungeordnete Sammlungen, sodass die Reihenfolge verloren geht. Beim Konvertieren eines Satzes in eine Liste wird eine beliebige Reihenfolge erstellt.
Ordnung aufrechterhalten
Wenn Ihnen die Reihenfolge wichtig ist, müssen Sie einen anderen Mechanismus verwenden. Eine sehr häufige Lösung hierfür besteht darin
OrderedDict
, die Reihenfolge der Schlüssel beim Einfügen beizubehalten:Ab Python 3.7 behält das integrierte Wörterbuch garantiert auch die Einfügereihenfolge bei. Sie können diese also auch direkt verwenden, wenn Sie Python 3.7 oder höher (oder CPython 3.6) verwenden:
Beachten Sie, dass dies möglicherweise einen gewissen Aufwand bedeutet, zuerst ein Wörterbuch und dann eine Liste daraus zu erstellen. Wenn Sie die Reihenfolge nicht wirklich beibehalten müssen, ist es oft besser, ein Set zu verwenden, insbesondere weil Sie dadurch viel mehr Operationen ausführen können. In dieser Frage finden Sie weitere Details und alternative Möglichkeiten, um die Reihenfolge beim Entfernen von Duplikaten beizubehalten.
Beachten Sie schließlich, dass sowohl die
set
als auch dieOrderedDict
/dict
-Lösungen erfordern, dass Ihre Artikel hashbar sind . Dies bedeutet normalerweise, dass sie unveränderlich sein müssen. Wenn Sie sich mit Elementen befassen müssen, die nicht hashbar sind (z. B. Listenobjekte), müssen Sie einen langsamen Ansatz verwenden, bei dem Sie grundsätzlich jedes Element mit jedem anderen Element in einer verschachtelten Schleife vergleichen müssen.quelle
In Python 2.7 ist die neue Methode zum Entfernen von Duplikaten aus einer iterierbaren Datei, während die ursprüngliche Reihenfolge beibehalten wird:
In Python 3.5 verfügt OrderedDict über eine C-Implementierung. Mein Timing zeigt, dass dies jetzt sowohl der schnellste als auch der kürzeste der verschiedenen Ansätze für Python 3.5 ist.
In Python 3.6 wurde das reguläre Diktat sowohl geordnet als auch kompakt. (Diese Funktion gilt für CPython und PyPy, ist jedoch in anderen Implementierungen möglicherweise nicht vorhanden.) Das gibt uns eine neue schnellste Möglichkeit zum Dedupieren unter Beibehaltung der Ordnung:
In Python 3.7 wird garantiert, dass das reguläre Diktat in allen Implementierungen geordnet ist. Die kürzeste und schnellste Lösung ist also:
quelle
TypeError: unhashable type: 'dictlist'
Es ist ein Einzeiler:
list(set(source_list))
wird den Trick machen.A
set
ist etwas, das unmöglich Duplikate haben kann.Update: Ein auftragserhaltender Ansatz besteht aus zwei Zeilen:
Hier verwenden wir die Tatsache, dass
OrderedDict
die Einfügereihenfolge von Schlüsseln gespeichert und nicht geändert wird, wenn ein Wert an einem bestimmten Schlüssel aktualisiert wird. Wir fügenTrue
als Werte ein, aber wir können alles einfügen, Werte werden einfach nicht verwendet. (Funktioniertset
sehr ähnlich wie adict
mit ignorierten Werten.)quelle
source_list
es hashbar ist.quelle
frozenset
mit nicht hashbaren Inhalten funktioniert. Ich erhalte immer noch den nicht hashbaren Fehler bei der Verwendungfrozenset
.Wenn Sie sich nicht für die Bestellung interessieren, gehen Sie einfach so vor:
A
set
hat garantiert keine Duplikate.quelle
l
es hashbar ist.Erstellen einer neuen Liste unter Beibehaltung der Reihenfolge der ersten Elemente von Duplikaten in
L
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]
zum Beispiel wird
if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]
dannnewlist
sein[1,2,3,4,5]
Dadurch wird überprüft, ob jedes neue Element zuvor nicht in der Liste angezeigt wurde, bevor es hinzugefügt wird. Auch braucht es keine Importe.
quelle
set
und habenOrderedDict
möglicherweise eine geringere Komplexität der amortisierten Zeit.Ein Kollege hat mir heute die akzeptierte Antwort als Teil seines Codes zur Codereview geschickt. Obwohl ich die Eleganz der fraglichen Antwort sicherlich bewundere, bin ich mit der Aufführung nicht zufrieden. Ich habe diese Lösung ausprobiert (ich verwende set , um die Suchzeit zu verkürzen).
Um die Effizienz zu vergleichen, habe ich eine Zufallsstichprobe von 100 Ganzzahlen verwendet - 62 waren eindeutig
Hier sind die Ergebnisse der Messungen
Was passiert, wenn set aus der Lösung entfernt wird?
Das Ergebnis ist nicht so schlecht wie beim OrderedDict , aber immer noch mehr als dreimal so hoch wie bei der ursprünglichen Lösung
quelle
def unique(iterable):
;seen = set()
;;seen_add = seen.add
;;return [item for item in iterable if not item in seen and not seen_add(item)]
Es gibt auch Lösungen mit Pandas und Numpy. Beide geben ein numpy-Array zurück, sodass Sie die Funktion verwenden müssen,
.tolist()
wenn Sie eine Liste wünschen.Pandas Lösung
Verwenden der Pandas-Funktion
unique()
:Numpy Lösung
Verwenden der Numpy-Funktion
unique()
.Beachten Sie, dass numpy.unique () auch die Werte sortiert . Die Liste
t2
wird also sortiert zurückgegeben. Wenn Sie die Reihenfolge beibehalten möchten, verwenden Sie wie in dieser Antwort :Die Lösung ist im Vergleich zu den anderen nicht so elegant. Im Vergleich zu pandas.unique () können Sie mit numpy.unique () auch überprüfen, ob verschachtelte Arrays entlang einer ausgewählten Achse eindeutig sind.
quelle
Eine andere Möglichkeit:
quelle
keys()
ein Wörterbuchansichtsobjekt zurückgegeben wird, keine Liste.Simpel und einfach:
Ausgabe:
quelle
in
ist O (n) Operation und Ihrcleanlist
Wille hat höchstensn
Zahlen => Worst-Case ~ O (n ^ 2)In dieser Antwort werden zwei Abschnitte aufgeführt: Zwei einzigartige Lösungen und ein Diagramm der Geschwindigkeit für bestimmte Lösungen.
Doppelte Elemente entfernen
Die meisten dieser Antworten entfernen nur doppelte Elemente, die hashbar sind. Diese Frage bedeutet jedoch nicht, dass nicht nur hashbare Elemente benötigt werden. Dies bedeutet, dass ich einige Lösungen anbieten werde, für die keine hashbaren Elemente erforderlich sind.
Sammlungen.Counter ist ein leistungsfähiges Werkzeug in der Standardbibliothek, das dafür perfekt sein könnte. Es gibt nur eine andere Lösung, die sogar Counter enthält. Diese Lösung ist jedoch auch auf Hash- Schlüssel beschränkt.
Um nicht zerlegbare Schlüssel in Counter zuzulassen, habe ich eine Container-Klasse erstellt, die versucht, die Standard-Hash-Funktion des Objekts abzurufen. Wenn dies jedoch fehlschlägt, wird die Identitätsfunktion ausprobiert. Es definiert auch eine Gleichung und eine Hash- Methode. Dies sollte ausreichen, um nicht zerlegbare Elemente in unserer Lösung zuzulassen . Nicht hashbare Objekte werden so behandelt, als wären sie hashbar. Diese Hash-Funktion verwendet jedoch die Identität für nicht verwertbare Objekte, was bedeutet, dass zwei gleiche Objekte, die beide nicht verwertbar sind, nicht funktionieren. Ich schlage vor, dass Sie dies überschreiben und ändern, um den Hash eines äquivalenten veränderlichen Typs zu verwenden (wie
hash(tuple(my_list))
wenn Sie ifmy_list
als Liste verwenden).Ich habe auch zwei Lösungen gemacht. Eine andere Lösung, die die Reihenfolge der Elemente beibehält und eine Unterklasse von OrderedDict und Counter mit dem Namen 'OrderedCounter' verwendet. Hier sind die Funktionen:
remd ist eine nicht geordnete Sortierung, oremd ist eine geordnete Sortierung. Sie können klar erkennen, welches schneller ist, aber ich werde es trotzdem erklären. Die nicht geordnete Sortierung ist etwas schneller. Es speichert weniger Daten, da keine Bestellung erforderlich ist.
Jetzt wollte ich auch die Geschwindigkeitsvergleiche jeder Antwort zeigen. Also mache ich das jetzt.
Welche Funktion ist die schnellste?
Zum Entfernen von Duplikaten habe ich aus einigen Antworten 10 Funktionen zusammengestellt. Ich habe die Geschwindigkeit jeder Funktion berechnet und sie mit matplotlib.pyplot in ein Diagramm eingefügt .
Ich habe dies in drei Grafikrunden unterteilt. Ein Hashable ist ein Objekt, das gehasht werden kann, ein Nicht-Hashable ist ein Objekt, das nicht gehasht werden kann. Eine geordnete Sequenz ist eine Sequenz, die die Ordnung beibehält, eine ungeordnete Sequenz bewahrt die Ordnung nicht. Hier noch ein paar Begriffe:
Ungeordnetes Hashable war für jede Methode geeignet, bei der Duplikate entfernt wurden, ohne dass die Reihenfolge eingehalten werden musste. Es musste nicht für Unashashables funktionieren, aber es konnte.
Bestelltes Hashable war für jede Methode geeignet, bei der die Reihenfolge der Elemente in der Liste beibehalten wurde, aber es musste nicht für nicht zerlegbare Elemente funktionieren, aber es konnte.
Ordered Unhashable war eine Methode, die die Reihenfolge der Elemente in der Liste beibehielt und für Unhashables funktionierte.
Auf der y-Achse ist die Anzahl der Sekunden angegeben.
Auf der x-Achse befindet sich die Nummer, auf die die Funktion angewendet wurde.
Wir haben Sequenzen für ungeordnete Hashables und geordnete Hashables mit folgendem Verständnis generiert:
[list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Für bestellte nicht zerlegbare Gegenstände:
[[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Beachten Sie, dass es einen "Schritt" im Bereich gibt, da dies ohne ihn 10x so lange gedauert hätte. Auch weil ich meiner persönlichen Meinung nach dachte, es hätte ein bisschen leichter zu lesen ausgesehen.
Beachten Sie auch, dass die Tasten in der Legende das sind, was ich als die wichtigsten Teile der Funktion erraten wollte. Welche Funktion hat das Schlimmste oder Beste? Die Grafik spricht für sich.
Nachdem dies erledigt ist, sind hier die Grafiken.
Ungeordnete Hashables
(Vergrößert)
Bestellte Hashables
(Vergrößert)
Bestellte Unhashables
(Vergrößert)
quelle
Ich hatte ein Diktat in meiner Liste, daher konnte ich den obigen Ansatz nicht verwenden. Ich habe den Fehler bekommen:
Wenn Sie sich also für die Bestellung interessieren und / oder einige Artikel nicht zerlegbar sind . Dann finden Sie dies vielleicht nützlich:
Einige halten Listenverständnis mit Nebeneffekten möglicherweise für keine gute Lösung. Hier ist eine Alternative:
quelle
map
mit einem Nebeneffekt ist noch irreführender als ein Listcomp mit einem Nebeneffekt. Auchlambda x: unique_list.append(x)
ist nur eine klobigere und langsamere Art zu passierenunique_list.append
.Alle Ordnungserhaltungsansätze, die ich bisher hier gesehen habe, verwenden entweder einen naiven Vergleich (bestenfalls mit O (n ^ 2) Zeitkomplexität) oder schwere
OrderedDicts
/set
+list
-Kombinationen, die auf hashbare Eingaben beschränkt sind. Hier ist eine Hash-unabhängige O (nlogn) -Lösung:Update fügte das
key
Argument, die Dokumentation und die Python 3-Kompatibilität hinzu.quelle
tuple()
Listen zu erstellen und sie zu hashen . | | | | - Im Allgemeinen dauert der Hash-Prozess eine Zeit, die proportional zur Größe der gesamten Daten ist, während diese Lösung eine Zeit O (nlog (n)) benötigt, die nur von der Länge der Liste abhängt.reduce()
arbeitet bereits an einer sortierten Sammlungsrt_enum
. Warum haben Sie sichsorted
erneut beworben ?Wenn Sie die Reihenfolge beibehalten und keine externen Module verwenden möchten, ist dies eine einfache Möglichkeit:
Hinweis: Bei dieser Methode wird die Reihenfolge des Erscheinungsbilds beibehalten. Wie oben dargestellt, werden neun nach dem anderen angezeigt, da es das erste Mal war, dass es angezeigt wurde. Dies ist jedoch das gleiche Ergebnis wie bei diesem Vorgang
aber es ist viel kürzer und läuft schneller.
Dies funktioniert, weil die
fromkeys
Funktion jedes Mal , wenn sie versucht, einen neuen Schlüssel zu erstellen, diesen einfach überschreibt, wenn er bereits vorhanden ist. Dies wirkt sich jedoch überhaupt nicht auf das Wörterbuch aus, dafromkeys
ein Wörterbuch erstellt wird, in dem alle Schlüssel den Wert habenNone
, sodass alle Duplikate auf diese Weise effektiv entfernt werden.quelle
Sie können dies auch tun:
Der Grund, warum dies funktioniert, ist, dass die
index
Methode nur den ersten Index eines Elements zurückgibt. Doppelte Elemente haben höhere Indizes. Siehe hier :quelle
list.index
ist eine Operation mit linearer Zeit, die Ihre Lösung quadratisch macht.Versuchen Sie es mit Sets:
quelle
Variante mit Bestellkonservierung reduzieren:
Angenommen, wir haben eine Liste:
Variante reduzieren (ineffizient):
5 x schneller, aber anspruchsvoller
Erläuterung:
quelle
Der beste Ansatz zum Entfernen von Duplikaten aus einer Liste ist die Verwendung der in Python verfügbaren Funktion set () , mit der diese Menge erneut in eine Liste konvertiert wird
quelle
Sie können die folgende Funktion verwenden:
Beispiel :
Verwendungszweck:
['this', 'is', 'a', 'list', 'with', 'dupicates', 'in', 'the']
quelle
Es gibt viele andere Antworten, die verschiedene Möglichkeiten vorschlagen, dies zu tun, aber alle sind Stapeloperationen, und einige von ihnen werfen die ursprüngliche Reihenfolge weg. Das mag je nach Bedarf in Ordnung sein, aber wenn Sie die Werte in der Reihenfolge der ersten Instanz jedes Werts durchlaufen möchten und die Duplikate im laufenden Betrieb im Vergleich zu allen auf einmal entfernen möchten, können Sie sie verwenden dieser Generator:
Dies gibt einen Generator / Iterator zurück, sodass Sie ihn überall dort verwenden können, wo Sie einen Iterator verwenden können.
Ausgabe:
Wenn Sie eine möchten
list
, können Sie dies tun:Ausgabe:
quelle
seen = set(iterable); for item in seen: yield item
ist mit ziemlicher Sicherheit schneller. (Ich habe diesen speziellen Fall nicht ausprobiert, aber das wäre meine Vermutung.)Ohne Set zu verwenden
quelle
Sie können
set
Duplikate entfernen:Beachten Sie jedoch, dass die Ergebnisse ungeordnet sind. Wenn das ein Problem ist:
quelle
Ein weiterer besserer Ansatz könnte sein:
und die Ordnung bleibt erhalten.
quelle
Dieser kümmert sich um die Bestellung ohne allzu großen Aufwand (OrderdDict & andere). Wahrscheinlich nicht der pythonischste oder kürzeste Weg, aber der Trick:
quelle
list
). 2. Ihre Methode skaliert extrem schlecht: Sie ist quadratisch in der Anzahl der Elemente inlist
.Der folgende Code ist einfach zum Entfernen von Duplikaten in der Liste
es gibt zurück [1,2,3,4]
quelle
list(set(..))
(über 1 Million Durchgänge) schlägt diese Lösung um ungefähr 10 ganze Sekunden - während dieser Ansatz ungefähr 12 Sekundenlist(set(..))
dauert , dauert er nur ungefähr 2 Sekunden!Hier ist die schnellste pythonische Lösung im Vergleich zu anderen in den Antworten aufgeführten.
Durch die Verwendung von Implementierungsdetails der Kurzschlussbewertung kann das Listenverständnis verwendet werden, das schnell genug ist.
visited.add(item)
Gibt immerNone
als Ergebnis zurück, das als ausgewertet wirdFalse
, sodass die rechte Seite vonor
immer das Ergebnis eines solchen Ausdrucks ist.Zeit es selbst
quelle
Mit set :
Verwenden von unique :
quelle
Unglücklicherweise. Die meisten Antworten hier behalten entweder die Reihenfolge nicht bei oder sind zu lang. Hier ist eine einfache, auftragserhaltende Antwort.
Dadurch erhalten Sie x mit entfernten Duplikaten, wobei die Reihenfolge beibehalten wird.
quelle
Sehr einfacher Weg in Python 3:
quelle
sorted(list(...))
ist redundant (sorted
konvertiert sein Argument bereits implizit in ein neueslist
, sortiert es und gibt das neue zurücklist
, sodass beide Mittel verwendet werden, um ein unnötiges temporäres Argument zu erstellenlist
). Nur verwenden,list
wenn das Ergebnis nicht sortiert werden muss. Nur verwenden,sorted
wenn das Ergebnis sortiert werden muss.Die Magie von Python Eingebauter Typ
In Python ist es sehr einfach, die komplizierten Fälle wie diese zu verarbeiten, und zwar nur nach dem in Python integrierten Typ.
Lassen Sie mich Ihnen zeigen, wie es geht!
Methode 1: Allgemeiner Fall
Die Möglichkeit ( 1 Zeilencode ), doppelte Elemente in der Liste zu entfernen und dennoch die Sortierreihenfolge beizubehalten
Sie erhalten das Ergebnis
Methode 2: Sonderfall
Der Sonderfall zur Verarbeitung nicht verwertbar ( 3 Zeilencodes )
Sie erhalten das Ergebnis:
Weil Tupel hashbar ist und Sie Daten einfach zwischen Liste und Tupel konvertieren können
quelle