Ich habe eine Liste von Diktaten und möchte die Diktate mit identischen Schlüssel- und Wertepaaren entfernen.
Für diese Liste: [{'a': 123}, {'b': 123}, {'a': 123}]
Ich möchte dies zurückgeben: [{'a': 123}, {'b': 123}]
Ein anderes Beispiel:
Für diese Liste: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
Ich möchte dies zurückgeben: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
python
list
dictionary
Brenden
quelle
quelle
set()
Antworten:
Versuche dies:
Die Strategie besteht darin, die Liste der Wörterbücher in eine Liste der Tupel zu konvertieren, in der die Tupel die Elemente des Wörterbuchs enthalten. Da die Tupel gehasht werden können, können Sie Duplikate mit entfernen
set
(unter Verwendung eines festgelegten Verständnisses wäre hier eine ältere Python-Alternativeset(tuple(d.items()) for d in l)
) und anschließend die Wörterbücher aus Tupeln mit neu erstellendict
.wo:
l
ist die ursprüngliche Listed
ist eines der Wörterbücher in der Listet
ist eines der aus einem Wörterbuch erstellten TupelBearbeiten: Wenn Sie die Bestellung beibehalten möchten, funktioniert der Einzeiler oben nicht, da dies
set
nicht der Fall ist . Mit ein paar Codezeilen können Sie dies jedoch auch tun:Beispielausgabe:
Hinweis: Wie von @alexis hervorgehoben, kann es vorkommen, dass zwei Wörterbücher mit denselben Schlüsseln und Werten nicht zu demselben Tupel führen. Dies kann passieren, wenn sie einen anderen Verlauf zum Hinzufügen / Entfernen von Schlüsseln durchlaufen. Wenn dies bei Ihrem Problem der Fall ist, sollten Sie die von ihm vorgeschlagene Sortierung in Betracht ziehen
d.items()
.quelle
d.items()
wird nicht garantiert, dass Elemente in einer bestimmten Reihenfolge zurückgegeben werden. Sie solltentuple(sorted(d.items()))
sicherstellen, dass Sie keine unterschiedlichen Tupel für dieselben Schlüssel-Wert-Paare erhalten.json
Modul wie ichEin weiterer Einzeiler, der auf Listenverständnissen basiert:
Da wir hier
dict
Vergleiche verwenden können, behalten wir nur die Elemente bei, die nicht in der restlichen Anfangsliste enthalten sind (auf diesen Begriff kann nur über den Index zugegriffen werdenn
, daher die Verwendung vonenumerate
).quelle
if i not in d[n + 1:]
iteriert über die gesamte Liste der Diktate (von,n
aber das halbiert nur die Gesamtzahl der Operationen) und Sie führen diese Prüfung für jedes Element in Ihrem Wörterbuch durch, so dass dieser Code O (n ^ 2) Zeitkomplexität istAndere Antworten funktionieren nicht, wenn Sie mit verschachtelten Wörterbüchern wie deserialisierten JSON-Objekten arbeiten. Für diesen Fall könnten Sie verwenden:
quelle
Wenn die Verwendung eines Pakets eines Drittanbieters in Ordnung wäre, können Sie Folgendes verwenden
iteration_utilities.unique_everseen
:Es behält die Reihenfolge der ursprünglichen Liste bei und ut kann auch nicht zerlegbare Elemente wie Wörterbücher verarbeiten, indem es auf einen langsameren Algorithmus zurückgreift (
O(n*m)
wobein
die Elemente in der ursprünglichen Liste undm
die eindeutigen Elemente in der ursprünglichen Liste statt sindO(n)
). Wenn sowohl Schlüssel als auch Werte hashbar sind, können Sie daskey
Argument dieser Funktion verwenden, um hashbare Elemente für den "Eindeutigkeitstest" zu erstellen (damit es funktioniertO(n)
).Im Fall eines Wörterbuchs (das unabhängig von der Reihenfolge vergleicht) müssen Sie es einer anderen Datenstruktur zuordnen, die so vergleichbar ist, zum Beispiel
frozenset
:Beachten Sie, dass Sie keinen einfachen
tuple
Ansatz verwenden sollten (ohne zu sortieren), da gleiche Wörterbücher nicht unbedingt dieselbe Reihenfolge haben müssen (selbst in Python 3.7, wo die Einfügereihenfolge - nicht die absolute Reihenfolge - garantiert ist):Und selbst das Sortieren des Tupels funktioniert möglicherweise nicht, wenn die Schlüssel nicht sortierbar sind:
Benchmark
Ich dachte, es könnte nützlich sein zu sehen, wie die Leistung dieser Ansätze verglichen wird, also habe ich einen kleinen Benchmark durchgeführt. Die Benchmark-Diagramme sind Zeit vs. Listengröße basierend auf einer Liste ohne Duplikate (die willkürlich ausgewählt wurde, ändert sich die Laufzeit nicht wesentlich, wenn ich einige oder viele Duplikate hinzufüge). Es ist ein Log-Log-Plot, sodass der gesamte Bereich abgedeckt ist.
Die absoluten Zeiten:
Die Zeiten relativ zum schnellsten Ansatz:
Der zweite Ansatz vom vierten Auge ist hier am schnellsten. Der
unique_everseen
Ansatz mit derkey
Funktion steht an zweiter Stelle, ist jedoch der schnellste Ansatz, der die Ordnung bewahrt. Die anderen Ansätze von jcollado und thefourtheye sind fast genauso schnell. Der Ansatzunique_everseen
ohne Schlüssel und die Lösungen von Emmanuel und Scorpil sind für längere Listen sehr langsam und verhalten sichO(n*n)
stattdessen viel schlechterO(n)
. stpks Ansatz mitjson
ist nicht,O(n*n)
aber es ist viel langsamer als die ähnlichenO(n)
Ansätze.Der Code zum Reproduzieren der Benchmarks:
Der Vollständigkeit halber ist hier der Zeitpunkt für eine Liste angegeben, die nur Duplikate enthält:
Die Timings ändern sich nicht wesentlich, außer
unique_everseen
ohnekey
Funktion, was in diesem Fall die schnellste Lösung ist. Dies ist jedoch nur der beste Fall (also nicht repräsentativ) für diese Funktion mit nicht zerlegbaren Werten, da ihre Laufzeit von der Anzahl der eindeutigen Werte in der Liste abhängt:O(n*m)
In diesem Fall ist sie nur 1 und wird daher ausgeführtO(n)
.Haftungsausschluss: Ich bin der Autor von
iteration_utilities
.quelle
Manchmal sind Loops im alten Stil immer noch nützlich. Dieser Code ist etwas länger als der von jcollado, aber sehr einfach zu lesen:
quelle
0
Inrange(0, len(a))
ist nicht notwendig.Wenn Sie die Bestellung beibehalten möchten, können Sie dies tun
Wenn die Reihenfolge keine Rolle spielt, können Sie dies tun
quelle
dict_values
Ausgabe anstelle einer Liste. Sie müssen das Ganze erneut in eine Liste aufnehmen.list(frozen.....)
Wenn Sie Pandas in Ihrem Workflow verwenden, können Sie eine Liste von Wörterbüchern direkt an den
pd.DataFrame
Konstruktor senden. Verwenden Sie danndrop_duplicates
undto_dict
Methoden für das gewünschte Ergebnis.quelle
Keine universelle Antwort , aber wenn Ihre Liste nach einem Schlüssel sortiert ist , wie folgt:
dann ist die Lösung so einfach wie:
Ergebnis:
Arbeitet mit verschachtelten Wörterbüchern und bewahrt (offensichtlich) die Ordnung.
quelle
Sie können ein Set verwenden, aber Sie müssen die Diktate in einen Hash-Typ verwandeln.
Einzigartig ist jetzt gleich
So erhalten Sie Diktate zurück:
quelle
d.iteritems()
ist nicht garantiert - daher kann es vorkommen, dass Sie "Duplikate" erhaltenunique
.Hier ist eine schnelle einzeilige Lösung mit einem doppelt verschachtelten Listenverständnis (basierend auf der Lösung von @Emmanuel).
Dabei wird
a
in jedem Diktat ein einzelner Schlüssel (z. B. ) als Primärschlüssel verwendet, anstatt zu prüfen, ob das gesamte Diktat übereinstimmtEs ist nicht das, wonach OP gefragt hat, aber es hat mich zu diesem Thread gebracht, also dachte ich mir, ich würde die Lösung veröffentlichen, mit der ich am Ende endete
quelle
Nicht so kurz, aber leicht zu lesen:
Jetzt hat die Liste
list_of_data_uniq
eindeutige Diktate.quelle