Nehmen wir an, ich habe zwei Listen l1
und l2
. Ich möchte durchführen l1 - l2
, was alle Elemente von l1
nicht in zurückgibt l2
.
Ich kann mir einen naiven Loop-Ansatz vorstellen, aber das wird wirklich ineffizient sein. Was ist eine pythonische und effiziente Methode, um dies zu tun?
Als Beispiel, wenn ich habe l1 = [1,2,6,8] and l2 = [2,3,5,8]
, l1 - l2
sollte zurückkehren[1,6]
Antworten:
Python verfügt über eine Sprachfunktion namens List Comprehensions , die sich perfekt dafür eignet, solche Dinge extrem einfach zu machen. Die folgende Anweisung macht genau das, was Sie wollen, und speichert das Ergebnis in
l3
:l3
wird enthalten[1, 6]
.quelle
in
Operator ist in einer Liste nicht so effizient.in
auf einer Liste ist O (n), währendin
auf einer Menge O (1) ist. Bis Sie jedoch zu Tausenden von Elementen oder mehr gelangen, werden Sie den Unterschied wahrscheinlich nicht bemerken.l3 = [x for x in l1 if x not in set(l2)]
? Ich bin sicher, wennset(l2)
ich mehr als einmal angerufen würde.l2s = set(l2)
und dann sagenl3 = [x for x in l1 if x not in l2s]
. Etwas einfacher.Eine Möglichkeit besteht darin, Sets zu verwenden:
quelle
l1
, was eine unerwünschte Nebenwirkung sein kann.timeit.timeit('a = [1,2,3,4]; b = [1,3]; c = [i for i in a if a not in b]', number=100000) -> 0.12061533199999985
timeit.timeit('a = {1,2,3,4}; b = {1,3}; c = a - b', number=100000) -> 0.04106225999998969
. Wenn also die Leistung ein wesentlicher Faktor ist, ist diese Antwort möglicherweise angemessener (und auch, wenn Sie sich nicht für Duplikate oder BestellungenAls Alternative können Sie auch verwenden ,
filter
mit dem Lambda - Ausdruck um das gewünschte Ergebnis zu erhalten. Zum Beispiel:Leistungsvergleich
Hier vergleiche ich die Leistung aller hier genannten Antworten. Wie erwartet ist der
set
Betrieb von Arkku am schnellsten.Arkkus eingestellter Unterschied - Zuerst (0,124 usec pro Schleife)
Daniel Prydens Listenverständnis mit
set
Nachschlagen - Zweiter (0,302 usec pro Schleife)Donuts Listenverständnis auf einfacher Liste - Dritter (0,552 usec pro Schleife)
Moinuddin Quadri verwendet
filter
- Viertens (0,972 usec pro Schleife)Akshay Hazari verwendet eine Kombination von
reduce
+filter
- Fünftel (3,97 usec pro Schleife)PS:
set
behält die Reihenfolge nicht bei und entfernt die doppelten Elemente aus der Liste. Verwenden Sie daher keine eingestellte Differenz, wenn Sie eine dieser benötigen.quelle
Wenn Sie die Antwort von Donut und die anderen Antworten hier erweitern, können Sie noch bessere Ergebnisse erzielen, indem Sie ein Generatorverständnis anstelle eines Listenverständnisses und eine
set
Datenstruktur verwenden (da derin
Operator O (n) in einer Liste ist, aber O (1). am Set).Hier ist eine Funktion, die für Sie funktionieren würde:
Das Ergebnis ist eine Iterierbarkeit, die die gefilterte Liste träge abruft. Wenn Sie ein echtes Listenobjekt benötigen (z. B. wenn Sie
len()
das Ergebnis bearbeiten müssen ), können Sie ganz einfach eine Liste wie folgt erstellen:quelle
Verwenden Sie den Python-Set-Typ. Das wäre das Pythonischste. :) :)
Da es nativ ist, sollte es auch die am besten optimierte Methode sein.
Sehen:
http://docs.python.org/library/stdtypes.html#set
http://docs.python.org/library/sets.htm (für ältere Python)
quelle
l1
wiederholte Elemente enthält.Verwenden Sie Set Comprehensions {x für x in l2} oder set (l2), um set zu erhalten, und verwenden Sie List Comprehensions , um die Liste abzurufen
Benchmark-Testcode:
Benchmark-Testergebnis:
quelle
l2set = set( l2 )
stattl2set = { x for x in l2 }
Alternative Lösung:
quelle