Ich muss zwei Listen vergleichen, um eine neue Liste spezifischer Elemente zu erstellen, die in einer Liste enthalten sind, in der anderen jedoch nicht. Beispielsweise:
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
Ich möchte list_1 durchlaufen und alle Elemente aus list_2 an main_list anhängen, die nicht in list_1 enthalten sind.
Das Ergebnis sollte sein:
main_list=["f", "m"]
Wie kann ich das mit Python machen?
list_2
, die nirgendwo in erscheinen,list_1
oder nach Elementenlist_2
, die nicht im selben Index vorhanden sindlist_1
?Antworten:
TL; DR:
LÖSUNG (1)
LÖSUNG (2) Sie möchten eine sortierte Liste
ERKLÄRUNGEN:
(1) Sie können NumPy die verwenden
setdiff1d
(array1
,array2
,assume_unique
=False
).assume_unique
fragt den Benutzer, WENN die Arrays BEREITS EINZIGARTIG SIND.Wenn
False
ja, werden zuerst die eindeutigen Elemente bestimmt.Wenn dies
True
der Fall ist , geht die Funktion davon aus, dass die Elemente bereits eindeutig sind. Die UND-Funktion überspringt die Bestimmung der eindeutigen Elemente.Dies ergibt die eindeutigen Werte
array1
, die nicht in sindarray2
.assume_unique
istFalse
standardmäßig.Wenn Sie sich mit den eindeutigen Elementen befassen (basierend auf der Antwort von Chinny84 ), verwenden Sie einfach (wobei
assume_unique=False
=> der Standardwert):(2) Für diejenigen, die Antworten sortieren möchten, habe ich eine benutzerdefinierte Funktion erstellt:
Um die Antwort zu erhalten, führen Sie Folgendes aus:
SEITLICHE HINWEISE:
(a) Lösung 2 (benutzerdefinierte Funktion
setdiff_sorted
) gibt eine Liste zurück (im Vergleich zu einem Array in Lösung 1).(b) Wenn Sie nicht sicher sind, ob die Elemente eindeutig sind, verwenden Sie einfach die Standardeinstellung von NumPy's
setdiff1d
in beiden Lösungen A und B. Was kann ein Beispiel für eine Komplikation sein? Siehe Anmerkung (c).(c) Die Dinge werden anders sein, wenn eine der beiden Listen nicht eindeutig ist.
Sprich
list_2
ist nicht eindeutig :list2 = ["a", "f", "c", "m", "m"]
. Behalten Sielist1
es bei:list_1 = ["a", "b", "c", "d", "e"]
Festlegen des Standardwerts für die
assume_unique
Ausbeuten["f", "m"]
(in beiden Lösungen). Wenn Sie jedoch einstellenassume_unique=True
, geben beide Lösungen["f", "m", "m"]
. Warum? Dies liegt daran, dass der Benutzer davon ausgegangen ist, dass die Elemente eindeutig sind. Daher ist es besser zu haltenassume_unique
auf den Standardwert. Beachten Sie, dass beide Antworten sortiert sind.Pythonnumpy
quelle
Sie können Sets verwenden:
Ausgabe:
Laut @ JonClements 'Kommentar ist hier eine übersichtlichere Version:
quelle
unique
Elemente kümmern , aber was ist, wenn wirm's
zum Beispiel mehrere haben, würde dies nicht aufgreifen.list(set(list_2).difference(list_1))
dass die expliziteset
Konvertierung vermieden wird ...Ich bin mir nicht sicher, warum die obigen Erklärungen so kompliziert sind, wenn native Methoden verfügbar sind:
quelle
Verwenden Sie ein Listenverständnis wie folgt:
Ausgabe:
Bearbeiten:
Wie in den Kommentaren unten erwähnt, ist das Obige bei großen Listen nicht die ideale Lösung. Wenn dies der Fall ist, wäre eine bessere Option die Konvertierung
list_1
in eineset
erste:quelle
list_1
, würden Sie wollen ein preconvertset
/frozenset
, zum Beispielset_1 = frozenset(list_1)
, dannmain_list = [item for item in list_2 if item not in set_1]
, die Verringerung der Prüfzeit vonO(n)
pro Artikel bis (etwa)O(1)
.enumerate()
:[index for (index, item) in enumerate(list_2) if item not in list_1]
Wenn Sie eine einzeilige Lösung (Ignorieren von Importen) wünschen, die nur
O(max(n, m))
Arbeit für Längeneingaben erfordertn
undm
nichtO(n * m)
funktioniert, können Sie dies mit demitertools
Modul tun :Dies nutzt die funktionalen Funktionen, die eine Rückruffunktion bei der Erstellung übernehmen, sodass der Rückruf einmal erstellt und für jedes Element wiederverwendet werden kann, ohne dass er irgendwo gespeichert werden muss (da
filterfalse
er intern gespeichert wird ). Listenverständnisse und Generatorausdrücke können dies, aber es ist hässlich. †Das ergibt die gleichen Ergebnisse in einer einzigen Zeile wie:
mit der Geschwindigkeit von:
Wenn die Vergleiche positionell sein sollen, gilt Folgendes:
sollte produzieren:
(weil der Wert in
list_2
eine Übereinstimmung mit demselben Index in hatlist_1
), sollten Sie auf jeden Fall mit Patricks Antwort gehen , die keine temporärenlist
s oderset
s beinhaltet (selbst wennset
s ungefähr istO(1)
, haben sie einen höheren "konstanten" Faktor pro Prüfung als einfache Gleichheitsprüfungen ) und beinhaltetO(min(n, m))
Arbeit, weniger als jede andere Antwort, und wenn Ihr Problem positionsempfindlich ist, ist dies die einzig richtige Lösung, wenn übereinstimmende Elemente bei nicht übereinstimmenden Offsets angezeigt werden.†: Der Weg, dasselbe mit einem Listenverständnis wie ein Einzeiler zu tun, besteht darin, verschachtelte Schleifen zu missbrauchen, um Werte in der "äußersten" Schleife zu erstellen und zwischenzuspeichern, z.
set_1
Dies bietet auch einen geringfügigen Leistungsvorteil für Python 3 (da jetzt der Verständniscode lokal festgelegt ist und nicht bei jeder Prüfung aus dem verschachtelten Bereich nachgeschlagen wird). Bei Python 2 spielt dies keine Rolle, da Python 2 keine Verschlüsse für Python 3 verwendet Listenverständnisse (sie arbeiten in demselben Bereich, in dem sie verwendet werden).quelle
Ausgabe:
quelle
list_1
groß ist, undlist_2
ist von nicht-trivialer Größe, weil es sich umlen(list_2)
O(n)
Scanslist_1
, so dass esO(n * m)
(won
undm
sind die Längenlist_2
undlist_1
jeweils). Wenn Sielist_1
in einset
/frozenset
im Voraus konvertieren , können die enthaltenen Überprüfungen durchgeführt werdenO(1)
, wodurch die GesamtarbeitO(n)
auf der Länge vonlist_2
(technisch gesehenO(max(n, m))
, da Sie daranO(m)
arbeiten, das zu erstellenset
) ausgeführt wird.Ich würde
zip
die Listen zusammenfügen, um sie Element für Element zu vergleichen.quelle
list
s handelt, wobei ein einzelnes neues erstelltlist
wird und keine zusätzlichen Provisorien erstellt werden , keine teuren Eindämmungsprüfungen usw.Ich habe zwei Methoden verwendet und fand eine Methode nützlich gegenüber der anderen. Hier ist meine Antwort:
Meine Eingabedaten:
Methode 1:
np.setdiff1d
Ich mag diesen Ansatz gegenüber anderen, weil er die Position beibehältMethode2: Es gibt zwar die gleiche Antwort wie in Methode1, stört aber die Reihenfolge
Methode1
np.setdiff1d
erfüllt meine Anforderungen perfekt. Diese Antwort zur Information.quelle
Wenn die Anzahl der Vorkommen berücksichtigt werden soll, müssen Sie wahrscheinlich Folgendes verwenden
collections.Counter
:Wie versprochen kann dies auch eine unterschiedliche Anzahl von Ereignissen als "Unterschied" behandeln:
quelle
Entfernen Sie aus ser1 die in ser2 vorhandenen Elemente.
Eingang
ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])
Lösung
ser1 [~ ser1.isin (ser2)]
quelle