wake-up-neo.com

Wie kann ich eine Liste von Listen/Sets in Python vergleichen?

Was ist der einfachste Weg, um die 2 Listen/Sets zu vergleichen und die Unterschiede auszugeben? Gibt es integrierte Funktionen, mit denen ich verschachtelte Listen/Sets vergleichen kann?

Eingaben:

First_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222],  
              ['Test3.doc', '3c3c3c', 3333]
             ]  
Secnd_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222], 
              ['Test3.doc', '8p8p8p', 9999], 
              ['Test4.doc', '4d4d4d', 4444]]  

Erwartete Ausgabe: 

Differences = [['Test3.doc', '3c3c3c', 3333],
               ['Test3.doc', '8p8p8p', 9999], 
               ['Test4.doc', '4d4d4d', 4444]]
24
tang

Sie wollen also den Unterschied zwischen zwei Artikellisten.

first_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222], 
              ['Test3.doc', '3c3c3c', 3333]]
secnd_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222], 
              ['Test3.doc', '8p8p8p', 9999], 
              ['Test4.doc', '4d4d4d', 4444]]

Zuerst würde ich jede Liste von Listen in eine Liste von Tupeln umwandeln, so dass Tupel hashierbar sind (Listen sind nicht), sodass Sie Ihre Liste von Tupeln in einen Satz von Tupeln konvertieren können:

first_Tuple_list = [Tuple(lst) for lst in first_list]
secnd_Tuple_list = [Tuple(lst) for lst in secnd_list]

Dann kannst du Sets machen:

first_set = set(first_Tuple_list)
secnd_set = set(secnd_Tuple_list)

EDIT (vorgeschlagen von sdolan): Sie hätten die letzten beiden Schritte für jede Liste in einem Einzeiler ausführen können:

first_set = set(map(Tuple, first_list))
secnd_set = set(map(Tuple, secnd_list))

Hinweis: map ist ein funktionaler Programmierbefehl, der die Funktion im ersten Argument (in diesem Fall die Funktion Tuple) auf jedes Element im zweiten Argument (in unserem Fall eine Listenliste) anwendet.

und finde den symmetrischen Unterschied zwischen den Sets:

>>> first_set.symmetric_difference(secnd_set) 
set([('Test3.doc', '3c3c3c', 3333),
     ('Test3.doc', '8p8p8p', 9999),
     ('Test4.doc', '4d4d4d', 4444)])

Hinweis first_set ^ secnd_set entspricht symmetric_difference.

Auch wenn Sie keine Sets verwenden möchten (z. B. Python 2.2), ist das ganz einfach. ZB mit Listenverständnissen:

>>> [x for x in first_list if x not in secnd_list] + [x for x in secnd_list if x not in first_list]
[['Test3.doc', '3c3c3c', 3333],
 ['Test3.doc', '8p8p8p', 9999],
 ['Test4.doc', '4d4d4d', 4444]]

oder mit den funktionalen Funktionen filter und lambda. (Sie müssen beide Möglichkeiten testen und kombinieren).

>>> filter(lambda x: x not in secnd_list, first_list) + filter(lambda x: x not in first_list, secnd_list)

[['Test3.doc', '3c3c3c', 3333],
 ['Test3.doc', '8p8p8p', 9999],
 ['Test4.doc', '4d4d4d', 4444]]
30
dr jimbob

Nicht sicher, ob es eine Nice-Funktion gibt, aber die "manuelle" Vorgehensweise ist nicht schwierig:

differences = []

for list in firstList:
    if list not in secondList:
        differences.append(list)
3
Sam Magura
>>> First_list = [['Test.doc', '1a1a1a', '1111'], ['Test2.doc', '2b2b2b', '2222'], ['Test3.doc', '3c3c3c', '3333']] 
>>> Secnd_list = [['Test.doc', '1a1a1a', '1111'], ['Test2.doc', '2b2b2b', '2222'], ['Test3.doc', '3c3c3c', '3333'], ['Test4.doc', '4d4d4d', '4444']] 


>>> z = [Tuple(y) for y in First_list]
>>> z
[('Test.doc', '1a1a1a', '1111'), ('Test2.doc', '2b2b2b', '2222'), ('Test3.doc', '3c3c3c', '3333')]
>>> x = [Tuple(y) for y in Secnd_list]
>>> x
[('Test.doc', '1a1a1a', '1111'), ('Test2.doc', '2b2b2b', '2222'), ('Test3.doc', '3c3c3c', '3333'), ('Test4.doc', '4d4d4d', '4444')]


>>> set(x) - set(z)
set([('Test4.doc', '4d4d4d', '4444')])
2
pyfunc

ich denke, Sie müssen Ihre Listen in Sets umwandeln:

>>> a = {('a', 'b'), ('c', 'd'), ('e', 'f')}
>>> b = {('a', 'b'), ('h', 'g')}
>>> a.symmetric_difference(b)
{('e', 'f'), ('h', 'g'), ('c', 'd')}
1
user126284

Durch die Verwendung von Satzverständnissen können Sie es zu einem Einzeiler machen. Falls Sie es wollen:

um ein paar Tupel zu bekommen, dann:

Differences = {Tuple(i) for i in First_list} ^ {Tuple(i) for i in Secnd_list}

Oder um eine Liste von Tupeln zu erhalten, dann:

Differences = list({Tuple(i) for i in First_list} ^ {Tuple(i) for i in Secnd_list})

Oder um eine Liste von Listen zu erhalten (wenn Sie wirklich wollen), dann:

Differences = [list(j) for j in {Tuple(i) for i in First_list} ^ {Tuple(i) for i in Secnd_list}]

PS: Ich habe hier gelesen: https://stackoverflow.com/a/10973817/4900095 dass die map () - Funktion keine Pythonic-Methode ist.

0
Sukrit Gupta

Alte Frage, aber hier ist eine Lösung, die ich verwende, um eindeutige Elemente zurückzugeben, die nicht in beiden Listen enthalten sind.

Ich verwende dies zum Vergleichen der von einer Datenbank zurückgegebenen Werte und der von einem Verzeichnis-Crawler-Paket generierten Werte. Die anderen Lösungen, die ich gefunden habe, haben mir nicht gefallen, da viele von ihnen nicht in der Lage waren, sowohl flache als auch geschachtelte Listen dynamisch zu verarbeiten.

def differentiate(x, y):
    """
    Retrieve a unique of list of elements that do not exist in both x and y.
    Capable of parsing one-dimensional (flat) and two-dimensional (lists of lists) lists.

    :param x: list #1
    :param y: list #2
    :return: list of unique values
    """
    # Validate both lists, confirm either are empty
    if len(x) == 0 and len(y) > 0:
        return y  # All y values are unique if x is empty
    Elif len(y) == 0 and len(x) > 0:
        return x  # All x values are unique if y is empty

    # Get the input type to convert back to before return
    try:
        input_type = type(x[0])
    except IndexError:
        input_type = type(y[0])

    # Dealing with a 2D dataset (list of lists)
    try:
        # Immutable and Unique - Convert list of tuples into set of tuples
        first_set = set(map(Tuple, x))
        secnd_set = set(map(Tuple, y))

    # Dealing with a 1D dataset (list of items)
    except TypeError:
        # Unique values only
        first_set = set(x)
        secnd_set = set(y)

    # Determine which list is longest
    longest = first_set if len(first_set) > len(secnd_set) else secnd_set
    shortest = secnd_set if len(first_set) > len(secnd_set) else first_set

    # Generate set of non-shared values and return list of values in original type
    return [input_type(i) for i in {i for i in longest if i not in shortest}]
0
Stephen Neal

http://docs.python.org/library/difflib.html ist ein guter Ausgangspunkt für das, wonach Sie suchen.

Wenn Sie es rekursiv auf die Deltas anwenden, sollten Sie in der Lage sein, verschachtelte Datenstrukturen zu behandeln. Aber es wird einige Arbeit brauchen.

0
btilly