web-dev-qa-db-de.com

Finden Sie nicht allgemeine Elemente in Listen

Ich versuche, ein Stück Code zu schreiben, das einen Ausdruck automatisch beeinflussen kann. Zum Beispiel Wenn ich zwei Listen [1,2,3,4] und [2,3,5] habe, sollte der Code die gemeinsamen Elemente in den beiden Listen finden können, [2,3]. und kombinieren Sie die restlichen Elemente in einer neuen Liste, nämlich [1,4,5]. 

Von diesem Beitrag: Wie finde ich eine Kreuzung? Ich sehe, dass die gemeinsamen Elemente durch gefunden werden können 

set([1,2,3,4]&set([2,3,5]). 

Gibt es eine einfache Möglichkeit, nicht übliche Elemente aus jeder Liste abzurufen, in meinem Beispiel [1,4] und [5]?

Ich kann eine For-Schleife machen:

lists = [[1,2,3,4],[2,3,5]]
conCommon = []
common = [2,3]
for elem in lists:
    for elem in eachList:
    if elem not in common:
        nonCommon += elem

Dies scheint jedoch überflüssig und ineffizient zu sein. Bietet Python eine praktische Funktion, die dies ermöglicht? Danke im Voraus!!

22
turtlesoup

Verwenden Sie den symmetrischen Differenzoperator für sets (auch bekannt als XOR - Operator):

>>> set([1,2,3]) ^ set([3,4,5])
set([1, 2, 4, 5])
45
Amber

Sie können das Intersection-Konzept verwenden, um solche Probleme zu lösen.

b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
set(b1).intersection(b2)
Out[22]: {4, 5}

Das Beste an diesem Code ist, dass er auch für große Daten ziemlich schnell funktioniert. Ich habe b1 mit 607139 und b2 mit 296029 Elementen, wenn ich diese Logik verwende, bekomme ich meine Ergebnisse in 2,9 Sekunden. 

12

Alte Frage, sieht aber so aus python hat eine eingebaute Funktion, die genau das bietet, wonach Sie suchen: .difference().

BEISPIEL

list_one = [1,2,3,4]
list_two = [2,3,5]

one_not_two = set(list_one).difference(list_two)
# set([1, 4])

two_not_one = set(list_two).difference(list_one)
# set([5])

Dies könnte auch geschrieben werden als:

one_not_two = set(list_one) - set(list_two)

Timing

Ich habe einige Timing-Tests für beide ausgeführt, und es scheint, dass .difference() eine leichte Flanke von 10-15% hat, aber jede Methode hat ungefähr eine Achtelsekunde gedauert, um 1M Elemente (zufällige ganze Zahlen zwischen 500) zu filtern und 100.000), es sei denn, Sie sind sehr zeitkritisch, ist es wahrscheinlich unerheblich.

Sonstige Hinweise

Es scheint, dass das OP nach einer Lösung sucht, die zwei separate Listen (oder Sätze) bereitstellt - eine, bei der die erste Elemente enthält, die nicht in der zweiten enthalten sind, und umgekehrt. Die meisten der vorherigen Antworten geben eine einzelne Liste oder Gruppe zurück, die alle Elemente enthält.

Es besteht auch die Frage, ob Elemente, die in der ersten Liste dupliziert werden können, mehrfach oder nur einmal gezählt werden sollen.

Wenn das OP Duplikate pflegen möchte, kann ein Listenverständnis verwendet werden, zum Beispiel:

one_not_two = [ x for x in list_one if x not in list_two ]
two_not_one = [ x for x in list_two if x not in list_one ]

... das ist ungefähr die gleiche Lösung wie in der ursprünglichen Frage, nur ein wenig sauberer. Diese Methode würde Duplikate aus der ursprünglichen Liste beibehalten, ist jedoch für größere Datensätze erheblich (wie mehrere Größenordnungen) langsamer.

1
elPastor

Sie können die Attributmethode .__xor__ verwenden. 

set([1,2,3,4]).__xor__(set([2,3,5]))

oder 

a = set([1,2,3,4])
b = set([2,3,5])
a.__xor__(b)
0
SuperNova