Holen Sie sich den Unterschied zwischen zwei Listen

810

Ich habe zwei Listen in Python, wie diese:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']

Ich muss eine dritte Liste mit Elementen aus der ersten Liste erstellen, die in der zweiten nicht vorhanden sind. Aus dem Beispiel muss ich bekommen:

temp3 = ['Three', 'Four']

Gibt es schnelle Wege ohne Zyklen und Überprüfung?

Max Frai
quelle
14
Sind die Elemente garantiert einzigartig? Wenn Sie temp1 = ['One', 'One', 'One']und haben temp2 = ['One'], wollen Sie ['One', 'One']zurück, oder []?
Michael Mrozek
@ Michael-Mrozek Sie sind einzigartig.
Max Frai
12
Möchten Sie die Reihenfolge der Elemente beibehalten?
Mark Byers

Antworten:

1209
In [5]: list(set(temp1) - set(temp2))
Out[5]: ['Four', 'Three']

Passen Sie auf das auf

In [5]: set([1, 2]) - set([2, 3])
Out[5]: set([1]) 

wo Sie vielleicht erwarten / wollen, dass es gleich ist set([1, 3]). Wenn Sie set([1, 3])als Antwort wollen, müssen Sie verwenden set([1, 2]).symmetric_difference(set([2, 3])).

ars
quelle
27
@Drewdin: Listen unterstützen den Operanden "-" nicht. Sets tun dies jedoch und das, was oben gezeigt wird, wenn Sie genau hinschauen.
Godsmith
1
danke, ich habe am Ende set (ListA) .symmetric_difference (ListB)
Drewdin
43
Die symmetrische Differenz kann geschrieben werden mit: ^ (set1 ^ set2)
Bastian
10
Könnten Sie bitte Ihre Antwort bearbeiten und darauf hinweisen, dass dies nur temp1-temp2 zurückgibt? .. Wie andere gesagt, um alle Unterschiede zurückzugeben, müssen Sie die sysmetrische Differenz verwenden: Liste (set (temp1) ^ set (temp2))
rkachach
Warum bekomme ich, TypeError: 'str' object is not callablewenn ich diese Operation am a = [1,2,2,2,3]undb = [2]
d8aninja
476

Die vorhandenen Lösungen bieten entweder das eine oder das andere von:

  • Schneller als O (n * m) Leistung.
  • Beibehaltung der Reihenfolge der Eingabeliste.

Aber bisher hat keine Lösung beides. Wenn Sie beides möchten, versuchen Sie Folgendes:

s = set(temp2)
temp3 = [x for x in temp1 if x not in s]

Leistungstest

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print timeit.timeit('list(set(temp1) - set(temp2))', init, number = 100000)
print timeit.timeit('s = set(temp2);[x for x in temp1 if x not in s]', init, number = 100000)
print timeit.timeit('[item for item in temp1 if item not in temp2]', init, number = 100000)

Ergebnisse:

4.34620224079 # ars' answer
4.2770634955  # This answer
30.7715615392 # matt b's answer

Die von mir vorgestellte Methode sowie die Beibehaltung der Ordnung ist auch (geringfügig) schneller als die Mengen-Subtraktion, da keine unnötige Menge erstellt werden muss. Der Leistungsunterschied wäre deutlicher, wenn die erste Liste erheblich länger als die zweite ist und wenn das Hashing teuer ist. Hier ist ein zweiter Test, der dies demonstriert:

init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''

Ergebnisse:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer
Mark Byers
quelle
2
Zusätzliche Unterstützung für diese Antwort: Es ist ein Anwendungsfall aufgetreten, bei dem die Beibehaltung der Listenreihenfolge für die Leistung wichtig war. Bei der Arbeit mit Tarinfo- oder Zipinfo-Objekten habe ich die Set-Subtraktion verwendet. So schließen Sie bestimmte Tarinfo-Objekte vom Extrahieren aus dem Archiv aus Das Erstellen der neuen Liste war schnell, aber beim Extrahieren sehr langsam. Der Grund ist mir zuerst entgangen. Es stellte sich heraus, dass die Neuordnung der Tarinfo-Objektliste einen enormen Leistungsverlust verursachte. Das Umschalten auf die Listenverständnismethode hat den Tag gerettet.
Ray Thompson
@ MarkByers - vielleicht sollte ich dafür eine ganz neue Frage schreiben. Aber wie würde das in einer Forloop funktionieren? Zum Beispiel, wenn sich mein Temp1 und Temp2 ständig ändern .. und ich die neuen Informationen an Temp3 anhängen möchte?
Ason
@ MarkByers - hört sich gut an. Ich werde noch ein bisschen darüber nachdenken. aber +1 für eine tolle Lösung.
Ason
Ich stimme @Dejel zu >>> temp1 = ['Eins', 'Zwei', 'Drei', 'Vier'] >>> temp2 = ['Eins', 'Zwei', 'Sechs'] >>> s = set (temp2) >>> temp3 = [x für x in temp1 wenn x nicht in s] >>> temp3 ['Drei', 'Vier']
earlonrails
3
@haccks Da das Überprüfen der Mitgliedschaft in einer Liste eine O (n) -Operation ist (die über die gesamte Liste iteriert), das Überprüfen der Mitgliedschaft in einer Menge jedoch O (1) ist.
Mark Byers
86
temp3 = [item for item in temp1 if item not in temp2]
matt b
quelle
15
Wenn Sie temp2sich vorher in ein Set verwandeln, wird dies ein bisschen effizienter.
Mondhorn
3
Richtig, hängt davon ab, ob Ockonal sich um Duplikate kümmert oder nicht (die ursprüngliche Frage sagt nichts aus)
matt b
2
Kommentar sagt, dass die (Listen | Tupel) keine Duplikate haben.
1
Ich habe Ihre Antwort positiv bewertet, weil ich zuerst dachte, Sie hätten Recht mit den Duplikaten. Aber item not in temp2und item not in set(temp2)wird immer die gleichen Ergebnisse zurückgeben, unabhängig davon, ob Duplikate vorhanden sind oder nicht temp2.
Arekolek
5
Stimmen Sie ab, wenn Sie nicht möchten, dass Listenelemente hashbar sind.
Brent
23

Der Unterschied zwischen zwei Listen (z. B. Liste1 und Liste2) kann mit der folgenden einfachen Funktion ermittelt werden.

def diff(list1, list2):
    c = set(list1).union(set(list2))  # or c = set(list1) | set(list2)
    d = set(list1).intersection(set(list2))  # or d = set(list1) & set(list2)
    return list(c - d)

oder

def diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))  # or return list(set(list1) ^ set(list2))

Mit der obigen Funktion kann der Unterschied mit diff(temp2, temp1)oder ermittelt werden diff(temp1, temp2). Beide geben das Ergebnis ['Four', 'Three']. Sie müssen sich keine Gedanken über die Reihenfolge der Liste machen oder darüber, welche Liste zuerst angegeben werden soll.

Python-Dokumentreferenz

arulmr
quelle
7
Warum nicht set (list1) .symmetric_difference (set (list2))?
swietyy
20

Für den Fall, dass Sie den Unterschied rekursiv möchten, habe ich ein Paket für Python geschrieben: https://github.com/seperman/deepdiff

Installation

Von PyPi installieren:

pip install deepdiff

Anwendungsbeispiel

Importieren

>>> from deepdiff import DeepDiff
>>> from pprint import pprint
>>> from __future__ import print_function # In case running on Python 2

Das gleiche Objekt wird leer zurückgegeben

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = t1
>>> print(DeepDiff(t1, t2))
{}

Der Typ eines Elements hat sich geändert

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:"2", 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{ 'type_changes': { 'root[2]': { 'newtype': <class 'str'>,
                                 'newvalue': '2',
                                 'oldtype': <class 'int'>,
                                 'oldvalue': 2}}}

Der Wert eines Artikels hat sich geändert

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:4, 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

Artikel hinzugefügt und / oder entfernt

>>> t1 = {1:1, 2:2, 3:3, 4:4}
>>> t2 = {1:1, 2:4, 3:3, 5:5, 6:6}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff)
{'dic_item_added': ['root[5]', 'root[6]'],
 'dic_item_removed': ['root[4]'],
 'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

String Unterschied

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world"}}
>>> t2 = {1:1, 2:4, 3:3, 4:{"a":"hello", "b":"world!"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { 'root[2]': {'newvalue': 4, 'oldvalue': 2},
                      "root[4]['b']": { 'newvalue': 'world!',
                                        'oldvalue': 'world'}}}

Saitendifferenz 2

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world!\nGoodbye!\n1\n2\nEnd"}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n1\n2\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { "root[4]['b']": { 'diff': '--- \n'
                                                '+++ \n'
                                                '@@ -1,5 +1,4 @@\n'
                                                '-world!\n'
                                                '-Goodbye!\n'
                                                '+world\n'
                                                ' 1\n'
                                                ' 2\n'
                                                ' End',
                                        'newvalue': 'world\n1\n2\nEnd',
                                        'oldvalue': 'world!\n'
                                                    'Goodbye!\n'
                                                    '1\n'
                                                    '2\n'
                                                    'End'}}}

>>> 
>>> print (ddiff['values_changed']["root[4]['b']"]["diff"])
--- 
+++ 
@@ -1,5 +1,4 @@
-world!
-Goodbye!
+world
 1
 2
 End

Typänderung

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n\n\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'type_changes': { "root[4]['b']": { 'newtype': <class 'str'>,
                                      'newvalue': 'world\n\n\nEnd',
                                      'oldtype': <class 'list'>,
                                      'oldvalue': [1, 2, 3]}}}

Listenunterschied

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3, 4]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{'iterable_item_removed': {"root[4]['b'][2]": 3, "root[4]['b'][3]": 4}}

Listenunterschied 2:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'iterable_item_added': {"root[4]['b'][3]": 3},
  'values_changed': { "root[4]['b'][1]": {'newvalue': 3, 'oldvalue': 2},
                      "root[4]['b'][2]": {'newvalue': 2, 'oldvalue': 3}}}

Listenunterschied ignorieren, Reihenfolge oder Duplikate ignorieren: (mit denselben Wörterbüchern wie oben)

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2, ignore_order=True)
>>> print (ddiff)
{}

Liste mit Wörterbuch:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:1, 2:2}]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:3}]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'dic_item_removed': ["root[4]['b'][2][2]"],
  'values_changed': {"root[4]['b'][2][1]": {'newvalue': 3, 'oldvalue': 1}}}

Sets:

>>> t1 = {1, 2, 8}
>>> t2 = {1, 2, 3, 5}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (DeepDiff(t1, t2))
{'set_item_added': ['root[3]', 'root[5]'], 'set_item_removed': ['root[8]']}

Benannte Tupel:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> t1 = Point(x=11, y=22)
>>> t2 = Point(x=11, y=23)
>>> pprint (DeepDiff(t1, t2))
{'values_changed': {'root.y': {'newvalue': 23, 'oldvalue': 22}}}

Benutzerdefinierte Objekte:

>>> class ClassA(object):
...     a = 1
...     def __init__(self, b):
...         self.b = b
... 
>>> t1 = ClassA(1)
>>> t2 = ClassA(2)
>>> 
>>> pprint(DeepDiff(t1, t2))
{'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}

Objektattribut hinzugefügt:

>>> t2.c = "new attribute"
>>> pprint(DeepDiff(t1, t2))
{'attribute_added': ['root.c'],
 'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}
Seperman
quelle
20

Kann mit dem Python XOR-Operator ausgeführt werden.

  • Dadurch werden die Duplikate in jeder Liste entfernt
  • Dies zeigt den Unterschied zwischen Temp1 und Temp2 und Temp2 und Temp1.

set(temp1) ^ set(temp2)
SuperNova
quelle
funktioniert, aber warum?
ZakS
die beste Antwort!
Artsiom Praneuski
Was für eine Antwort! so pythonisch !!!! erstaunlich
toing_toing
18

einfachster Weg,

benutze set (). different (set ())

list_a = [1,2,3]
list_b = [2,3]
print set(list_a).difference(set(list_b))

Antwort ist set([1])

kann als Liste drucken,

print list(set(list_a).difference(set(list_b)))
Mohideen bin Mohammed
quelle
14

Wenn Sie sich wirklich mit Leistung beschäftigen, verwenden Sie numpy!

Hier ist das vollständige Notizbuch als Kernstück von Github mit Vergleich zwischen Liste, Numpy und Pandas.

https://gist.github.com/denfromufa/2821ff59b02e9482be15d27f2bbd4451

Geben Sie hier die Bildbeschreibung ein

denfromufa
quelle
Ich habe das Notizbuch im Link und auch den Screenshot aktualisiert. Überraschenderweise ist Pandas langsamer als Numpy, selbst wenn intern auf Hashtable umgeschaltet wird. Teilweise liegt dies möglicherweise an der Übertragung auf int64.
Denfromufa
13

Ich werde einwerfen, da keine der vorliegenden Lösungen ein Tupel ergibt:

temp3 = tuple(set(temp1) - set(temp2))

Alternative:

#edited using @Mark Byers idea. If you accept this one as answer, just accept his instead.
temp3 = tuple(x for x in temp1 if x not in set(temp2))

Wie das andere Nicht-Tupel, das Antworten in diese Richtung liefert, bewahrt es die Ordnung

aaronasterling
quelle
11

Ich wollte etwas , das zwei Listen nehmen würde und könnte tun , was diffin dem bashFall ist. Da diese Frage zuerst auftaucht, wenn Sie nach "Python Diff Two Lists" suchen und nicht sehr spezifisch ist, werde ich veröffentlichen, was ich mir ausgedacht habe.

Mit SequenceMatherfrom können difflibSie zwei Listen wie difffolgt vergleichen. Keine der anderen Antworten sagt Ihnen die Position, an der der Unterschied auftritt, aber diese tut es. Einige Antworten geben den Unterschied nur in eine Richtung. Einige ordnen die Elemente neu. Einige behandeln keine Duplikate. Diese Lösung bietet jedoch einen echten Unterschied zwischen zwei Listen:

a = 'A quick fox jumps the lazy dog'.split()
b = 'A quick brown mouse jumps over the dog'.split()

from difflib import SequenceMatcher

for tag, i, j, k, l in SequenceMatcher(None, a, b).get_opcodes():
  if tag == 'equal': print('both have', a[i:j])
  if tag in ('delete', 'replace'): print('  1st has', a[i:j])
  if tag in ('insert', 'replace'): print('  2nd has', b[k:l])

Dies gibt aus:

both have ['A', 'quick']
  1st has ['fox']
  2nd has ['brown', 'mouse']
both have ['jumps']
  2nd has ['over']
both have ['the']
  1st has ['lazy']
both have ['dog']

Wenn Ihre Bewerbung dieselben Annahmen trifft wie die anderen Antworten, profitieren Sie natürlich am meisten davon. Aber wenn Sie nach einem wahren suchendiff Funktionalität , ist dies der einzige Weg.

Zum Beispiel könnte keine der anderen Antworten Folgendes verarbeiten:

a = [1,2,3,4,5]
b = [5,4,3,2,1]

Aber dieser tut:

  2nd has [5, 4, 3, 2]
both have [1]
  1st has [2, 3, 4, 5]
Arekolek
quelle
10

Versuche dies:

temp3 = set(temp1) - set(temp2)
Maciej Kucharz
quelle
10

Dies könnte sogar schneller sein als Marks Listenverständnis:

list(itertools.filterfalse(set(temp2).__contains__, temp1))
Mohammed
quelle
7
Vielleicht möchten Sie das from itertools import filterfalseBit hier einfügen. Beachten Sie auch, dass dies keine Sequenz wie die anderen zurückgibt, sondern einen Iterator.
Matt Luongo
7

Hier ist eine CounterAntwort für den einfachsten Fall.

Dies ist kürzer als die obige, die Zwei-Wege-Unterschiede bewirkt, da sie nur genau das tut, was die Frage verlangt: Generieren Sie eine Liste der Inhalte in der ersten Liste, nicht jedoch der zweiten.

from collections import Counter

lst1 = ['One', 'Two', 'Three', 'Four']
lst2 = ['One', 'Two']

c1 = Counter(lst1)
c2 = Counter(lst2)
diff = list((c1 - c2).elements())

Abhängig von Ihren Lesbarkeitspräferenzen ergibt sich alternativ ein anständiger Einzeiler:

diff = list((Counter(lst1) - Counter(lst2)).elements())

Ausgabe:

['Three', 'Four']

Beachten Sie, dass Sie den list(...)Anruf entfernen können, wenn Sie ihn nur durchlaufen.

Da diese Lösung Zähler verwendet, werden Mengen im Vergleich zu den vielen satzbasierten Antworten richtig behandelt. Zum Beispiel zu diesem Eingang:

lst1 = ['One', 'Two', 'Two', 'Two', 'Three', 'Three', 'Four']
lst2 = ['One', 'Two']

Die Ausgabe ist:

['Two', 'Two', 'Three', 'Three', 'Four']
Taylor Edmiston
quelle
5

Sie können eine naive Methode verwenden, wenn die Elemente der Difflist sortiert und festgelegt sind.

list1=[1,2,3,4,5]
list2=[1,2,3]

print list1[len(list2):]

oder mit nativen Set-Methoden:

subset=set(list1).difference(list2)

print subset

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print "Naive solution: ", timeit.timeit('temp1[len(temp2):]', init, number = 100000)
print "Native set solution: ", timeit.timeit('set(temp1).difference(temp2)', init, number = 100000)

Naive Lösung: 0,0787101593292

Native Set-Lösung: 0.998837615564

Soundcorner
quelle
5

Ich bin etwas zu spät im Spiel dafür, aber Sie können einen Vergleich der Leistung einiger der oben genannten Codes mit diesem machen, zwei der schnellsten Konkurrenten sind,

list(set(x).symmetric_difference(set(y)))
list(set(x) ^ set(y))

Ich entschuldige mich für die elementare Ebene der Codierung.

import time
import random
from itertools import filterfalse

# 1 - performance (time taken)
# 2 - correctness (answer - 1,4,5,6)
# set performance
performance = 1
numberoftests = 7

def answer(x,y,z):
    if z == 0:
        start = time.clock()
        lists = (str(list(set(x)-set(y))+list(set(y)-set(y))))
        times = ("1 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 1:
        start = time.clock()
        lists = (str(list(set(x).symmetric_difference(set(y)))))
        times = ("2 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 2:
        start = time.clock()
        lists = (str(list(set(x) ^ set(y))))
        times = ("3 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 3:
        start = time.clock()
        lists = (filterfalse(set(y).__contains__, x))
        times = ("4 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 4:
        start = time.clock()
        lists = (tuple(set(x) - set(y)))
        times = ("5 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 5:
        start = time.clock()
        lists = ([tt for tt in x if tt not in y])
        times = ("6 = " + str(time.clock() - start))
        return (lists,times)

    else:    
        start = time.clock()
        Xarray = [iDa for iDa in x if iDa not in y]
        Yarray = [iDb for iDb in y if iDb not in x]
        lists = (str(Xarray + Yarray))
        times = ("7 = " + str(time.clock() - start))
        return (lists,times)

n = numberoftests

if performance == 2:
    a = [1,2,3,4,5]
    b = [3,2,6]
    for c in range(0,n):
        d = answer(a,b,c)
        print(d[0])

elif performance == 1:
    for tests in range(0,10):
        print("Test Number" + str(tests + 1))
        a = random.sample(range(1, 900000), 9999)
        b = random.sample(range(1, 900000), 9999)
        for c in range(0,n):
            #if c not in (1,4,5,6):
            d = answer(a,b,c)
            print(d[1])
Alex Jacob
quelle
5

Hier sind einige einfache, auftragserhaltende Möglichkeiten, zwei Listen von Zeichenfolgen zu unterscheiden.

Code

Ein ungewöhnlicher Ansatz mit pathlib:

import pathlib


temp1 = ["One", "Two", "Three", "Four"]
temp2 = ["One", "Two"]

p = pathlib.Path(*temp1)
r = p.relative_to(*temp2)
list(r.parts)
# ['Three', 'Four']

Dies setzt voraus, dass beide Listen Zeichenfolgen mit äquivalenten Anfängen enthalten. Weitere Informationen finden Sie in den Dokumenten . Beachten Sie, dass es im Vergleich zu festgelegten Operationen nicht besonders schnell ist.


Eine einfache Implementierung mit itertools.zip_longest:

import itertools as it


[x for x, y in it.zip_longest(temp1, temp2) if x != y]
# ['Three', 'Four']
Pylang
quelle
1
Die itertools Lösung funktioniert nur , wenn die Elemente in temp1und temp2Linie sich gut. Wenn Sie zum Beispiel die Elemente umdrehen temp2oder am Anfang einen anderen Wert einfügen temp2, gibt der listcomp nur die gleichen Elemente zurück wie intemp1
KenHBS
Ja, es ist ein Merkmal dieser Ansätze. Wie bereits erwähnt, behalten diese Lösungen die Reihenfolge bei - sie setzen eine relative Reihenfolge zwischen den Listen voraus. Eine ungeordnete Lösung wäre, zwei Sätze zu unterscheiden.
Pylang
4

Dies ist eine andere Lösung:

def diff(a, b):
    xa = [i for i in set(a) if i not in b]
    xb = [i for i in set(b) if i not in a]
    return xa + xb
manhgd
quelle
4

Wenn Sie auf TypeError: unhashable type: 'list'etwas stoßen, müssen Sie Listen oder Sets in Tupel umwandeln, z

set(map(tuple, list_of_lists1)).symmetric_difference(set(map(tuple, list_of_lists2)))

Siehe auch Wie vergleiche ich eine Liste von Listen / Sets in Python?

kqw
quelle
4

Nehmen wir an, wir haben zwei Listen

list1 = [1, 3, 5, 7, 9]
list2 = [1, 2, 3, 4, 5]

Aus den beiden obigen Listen ist ersichtlich, dass die Punkte 1, 3, 5 in Liste 2 vorhanden sind und die Punkte 7, 9 nicht. Andererseits sind die Punkte 1, 3, 5 in Liste 1 vorhanden und die Punkte 2, 4 nicht.

Was ist die beste Lösung, um eine neue Liste mit den Elementen 7, 9 und 2, 4 zurückzugeben?

Alle obigen Antworten finden die Lösung. Was ist nun die optimalste?

def difference(list1, list2):
    new_list = []
    for i in list1:
        if i not in list2:
            new_list.append(i)

    for j in list2:
        if j not in list1:
            new_list.append(j)
    return new_list

gegen

def sym_diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))

Mit timeit können wir die Ergebnisse sehen

t1 = timeit.Timer("difference(list1, list2)", "from __main__ import difference, 
list1, list2")
t2 = timeit.Timer("sym_diff(list1, list2)", "from __main__ import sym_diff, 
list1, list2")

print('Using two for loops', t1.timeit(number=100000), 'Milliseconds')
print('Using two for loops', t2.timeit(number=100000), 'Milliseconds')

kehrt zurück

[7, 9, 2, 4]
Using two for loops 0.11572412995155901 Milliseconds
Using symmetric_difference 0.11285737506113946 Milliseconds

Process finished with exit code 0
Carson
quelle
3

einzeilige Version der Arulmr- Lösung

def diff(listA, listB):
    return set(listA) - set(listB) | set(listA) -set(listB)
Sreemanth Pulagam
quelle
3

Wenn Sie mehr wie ein Änderungssatz möchten, können Sie Counter verwenden

from collections import Counter

def diff(a, b):
  """ more verbose than needs to be, for clarity """
  ca, cb = Counter(a), Counter(b)
  to_add = cb - ca
  to_remove = ca - cb
  changes = Counter(to_add)
  changes.subtract(to_remove)
  return changes

lista = ['one', 'three', 'four', 'four', 'one']
listb = ['one', 'two', 'three']

In [127]: diff(lista, listb)
Out[127]: Counter({'two': 1, 'one': -1, 'four': -2})
# in order to go from lista to list b, you need to add a "two", remove a "one", and remove two "four"s

In [128]: diff(listb, lista)
Out[128]: Counter({'four': 2, 'one': 1, 'two': -1})
# in order to go from listb to lista, you must add two "four"s, add a "one", and remove a "two"
Nick Franceschina
quelle
2

Wir können Schnittpunkt minus Vereinigung von Listen berechnen:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two', 'Five']

set(temp1+temp2)-(set(temp1)&set(temp2))

Out: set(['Four', 'Five', 'Three']) 
Mohammad Etemaddar
quelle
2

Dies kann mit einer Zeile gelöst werden. Die Frage wird gegeben, zwei Listen (temp1 und temp2) geben ihre Differenz in einer dritten Liste (temp3) zurück.

temp3 = list(set(temp1).difference(set(temp2)))
fgaim
quelle
1

Hier ist eine einfache Möglichkeit, zwei Listen zu unterscheiden (unabhängig vom Inhalt). Sie können das Ergebnis wie folgt erhalten:

>>> from sets import Set
>>>
>>> l1 = ['xvda', False, 'xvdbb', 12, 'xvdbc']
>>> l2 = ['xvda', 'xvdbb', 'xvdbc', 'xvdbd', None]
>>>
>>> Set(l1).symmetric_difference(Set(l2))
Set([False, 'xvdbd', None, 12])

Hoffe das wird hilfreich.

SK Venkat
quelle
0

Ich bevorzuge die Konvertierung in Mengen und dann die Funktion "different ()". Der vollständige Code lautet:

temp1 = ['One', 'Two', 'Three', 'Four'  ]                   
temp2 = ['One', 'Two']
set1 = set(temp1)
set2 = set(temp2)
set3 = set1.difference(set2)
temp3 = list(set3)
print(temp3)

Ausgabe:

>>>print(temp3)
['Three', 'Four']

Es ist am einfachsten zu verstehen, und wenn Sie in Zukunft mit großen Datenmengen arbeiten, werden Duplikate entfernt, wenn keine Duplikate erforderlich sind. Ich hoffe es hilft ;-)

Shakhyar Gogoi
quelle
-1
(list(set(a)-set(b))+list(set(b)-set(a)))
Nadhem
quelle
3
Können Sie neben der Antwort auch eine Erklärung geben, wie es funktioniert / auf dieses spezielle Problem zutrifft? Antworten und Lösungen sind großartig, aber detaillierte Anleitungen und Erklärungen sind unendlich besser.
Busse
-1
def diffList(list1, list2):     # returns the difference between two lists.
    if len(list1) > len(list2):
        return (list(set(list1) - set(list2)))
    else:
        return (list(set(list2) - set(list1)))

zB wenn list1 = [10, 15, 20, 25, 30, 35, 40]und list2 = [25, 40, 35]dann wird die zurückgegebene Liste seinoutput = [10, 20, 30, 15]

csg
quelle
Sie können dies nicht für Differenzoperationen tun. Selbst bei ganzen Zahlen soll eine Funktion, die 'a - b' ausführen soll, nur 'b' von 'a' subtrahieren, unabhängig davon, ob 'b' größer als 'a' ist oder nicht. Ähnliches gilt für Listen und Mengen. A - B und B - A können beide gültige Operationen sein, unabhängig von der Länge von A und B, Sie müssen nur den Inhalt von B von A ausschließen, um A - B auszuführen.
Abu Talha Danish