Holen Sie sich den Unterschied zwischen zwei Listen mit eindeutigen Einträgen

Lesezeit: 8 Minuten

Benutzeravatar von Max Frai
Max Frai

Ich habe zwei Listen in Python:

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

Unter der Annahme, dass die Elemente in jeder Liste eindeutig sind, möchte ich eine dritte Liste mit Elementen aus der ersten Liste erstellen, die nicht in der zweiten Liste enthalten sind:

temp3 = ['Three', 'Four']

Gibt es schnelle Wege ohne Zyklen und Kontrollen?

  • Sind die Elemente garantiert einzigartig? Wenn Sie haben temp1 = ['One', 'One', 'One'] und temp2 = ['One']willst du ['One', 'One'] zurück, bzw []?

    – Michael Mrozek

    11. August 2010 um 19:43 Uhr

  • @michael-mrozek sie sind einzigartig.

    – Max Frai

    11. August 2010 um 19:45 Uhr

  • Möchten Sie die Reihenfolge der Elemente beibehalten?

    – Mark Byers

    11. August 2010 um 19:49 Uhr

  • Beantwortet das deine Frage? Elemente finden, die nicht in einer Liste enthalten sind

    – Goncalo Peres

    28. April 2021 um 8:48 Uhr

Benutzeravatar von Mark Byers
Markus Byers

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

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

Aber bisher hat keine Lösung beides. Wenn Sie beides wollen, 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 Reihenfolge ist auch (etwas) schneller als die Mengensubtraktion, da sie keine Konstruktion einer unnötigen Menge erfordert. Der Leistungsunterschied wäre deutlicher, wenn die erste Liste erheblich länger als die zweite ist und 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

  • Zusätzliche Unterstützung für diese Antwort: Ist auf einen Anwendungsfall gestoßen, 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. Um bestimmte tarinfo-Objekte von der Extraktion aus dem Archiv auszuschließen. Das Erstellen der neuen Liste war schnell, aber während der Extraktion sehr langsam. Der Grund entging mir zunächst. Es stellte sich heraus, dass die Neuordnung der tarinfo-Objektliste zu einer enormen Leistungseinbuße führte. Der Wechsel zur Listenverständnismethode rettete den Tag.

    – Ray Thompson

    13. Dezember 2011 um 0:26 Uhr


  • @MarkByers – vielleicht sollte ich dafür eine ganz neue Frage schreiben. Aber wie würde das in einer Forloop funktionieren? Zum Beispiel, wenn sich meine temp1 und temp2 ständig ändern … und ich die neuen Informationen an temp3 anhängen möchte?

    – Einen Sohn

    9. August 2012 um 17:57 Uhr

  • @ MarkByers – hört sich gut an. Ich werde noch ein bisschen darüber nachdenken. aber +1 für eine großartige Lösung.

    – Einen Sohn

    9. August 2012 um 18:39 Uhr

  • Könnten Sie bitte erklären, warum Ihr Code weniger Zeit in Anspruch nimmt als die Antwort von Matt? @MarkByers

    – Hacken

    5. November 2015 um 16:36 Uhr

  • @hackks Weil die Überprüfung der Mitgliedschaft in einer Liste eine O (n) -Operation ist (Iteration über die gesamte Liste), die Überprüfung der Mitgliedschaft in einer Menge jedoch O (1) ist.

    – Mark Byers

    5. November 2015 um 16:57 Uhr

  • Guter Fund! Diesen Abschnitt der Dokumentation habe ich immer übersehen: docs.python.org/3/library/….

    Benutzer3521099

    28. Dezember 2020 um 16:09 Uhr

  • Dies ist das Beste für einen 2-Seiten-Unterschied

    – EuberEntwickler

    17. März 2021 um 22:35 Uhr

  • Auf jeden Fall die beste Antwort, die die Frage des OP direkt anspricht: “Unterschied zwischen zwei Listen ermitteln”. Die anderen sind mit Seitenkoffern zu kompliziert. Und es gibt keine Datentypkonvertierung.

    – Rich Lysakowski PhD

    7. April 2021 um 3:25 Uhr

  • funktioniert dies besser als jede andere Lösung bzgl. der Zeit?

    – Gangula

    13. September 2021 um 9:11 Uhr

  • @Gangula Um den Unterschied zwischen den beiden Methoden zu sehen, fügen Sie einen Wert hinzu temp2 das ist nicht dabei temp1 und versuche es erneut.

    – urig

    19. Oktober 2021 um 5:41 Uhr

Benutzeravatar von matt b
matt b

Sie könnten das Listenverständnis verwenden:

temp3 = [item for item in temp1 if item not in temp2]

  • Drehen temp2 in einen Satz davor würde dies etwas effizienter machen.

    Benutzer355252

    11. August 2010 um 19:47 Uhr

  • Richtig, hängt davon ab, ob Ockonal sich um Duplikate kümmert oder nicht (ursprüngliche Frage sagt nichts)

    – matt b

    11. August 2010 um 19:47 Uhr

  • Kommentar sagt, dass die (Listen|Tupel) keine Duplikate haben.

    Benutzer395760

    11. August 2010 um 19:52 Uhr

  • Ich habe Ihre Antwort positiv bewertet, weil ich dachte, Sie hätten zunächst Recht mit den Duplikaten. Aber item not in temp2 und item not in set(temp2) gibt immer dieselben Ergebnisse zurück, unabhängig davon, ob Duplikate vorhanden sind oder nicht temp2.

    – arekolek

    7. März 2016 um 22:42 Uhr


  • Stimmen Sie dafür, dass Listenelemente nicht hashfähig sein müssen.

    – Brent

    11. September 2017 um 15:19 Uhr

Benutzeravatar von Maciej Kucharz
Maciej Kucharz

Versuche dies:

temp3 = set(temp1) - set(temp2)

  • Drehen temp2 in einen Satz davor würde dies etwas effizienter machen.

    Benutzer355252

    11. August 2010 um 19:47 Uhr

  • Richtig, hängt davon ab, ob Ockonal sich um Duplikate kümmert oder nicht (ursprüngliche Frage sagt nichts)

    – matt b

    11. August 2010 um 19:47 Uhr

  • Kommentar sagt, dass die (Listen|Tupel) keine Duplikate haben.

    Benutzer395760

    11. August 2010 um 19:52 Uhr

  • Ich habe Ihre Antwort positiv bewertet, weil ich dachte, Sie hätten zunächst Recht mit den Duplikaten. Aber item not in temp2 und item not in set(temp2) gibt immer dieselben Ergebnisse zurück, unabhängig davon, ob Duplikate vorhanden sind oder nicht temp2.

    – arekolek

    7. März 2016 um 22:42 Uhr


  • Stimmen Sie dafür, dass Listenelemente nicht hashfähig sein müssen.

    – Brent

    11. September 2017 um 15:19 Uhr

Falls Sie den Unterschied rekursiv wollen, habe ich ein Paket für Python geschrieben:
https://github.com/seperman/deepdiff

Installation

Von PyPi installieren:

pip install deepdiff

Beispielnutzung

Importieren

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

Dasselbe Objekt gibt leer zurück

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

Art eines Artikels 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}}}

Element 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}}}

Saitenunterschied

>>> 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'}}}

Saitenunterschied 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 ändern

>>> 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]}}}

Unterschied auflisten

>>> 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}}}

Unterschiede auflisten, Reihenfolge ignorieren oder Duplikate: (mit den gleichen 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, die Wörterbuch enthält:

>>> 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}}}

1440720cookie-checkHolen Sie sich den Unterschied zwischen zwei Listen mit eindeutigen Einträgen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy