web-dev-qa-db-fra.com

Comment comparer une liste de listes/ensembles en python?

Quel est le moyen le plus simple de comparer les 2 listes/ensembles et d’en extraire les différences? Existe-t-il des fonctions intégrées qui m'aideront à comparer les listes/ensembles imbriqués?

Contributions:

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

Production attendue: 

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

Donc, vous voulez la différence entre deux listes d'éléments.

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

Premièrement, je transformerais chaque liste de listes en une liste de n-uplets, afin que les n-uplets puissent être remplis (les listes ne le soient pas) afin que vous puissiez convertir votre liste de n-uplets en un ensemble de n-uplets:

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

Ensuite, vous pouvez faire des ensembles:

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

EDIT (suggéré par sdolan): Vous auriez pu faire les deux dernières étapes pour chaque liste en une ligne:

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

Remarque: map est une commande de programmation fonctionnelle qui applique la fonction dans le premier argument (dans ce cas, la fonction Tuple) à chaque élément du deuxième argument (qui dans notre cas est une liste de listes).

et trouvez la différence symétrique entre les ensembles:

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

Remarque: first_set ^ secnd_set est équivalent à symmetric_difference.

De plus, si vous ne voulez pas utiliser d'ensembles (par exemple, en utilisant python 2.2), sa tâche est simple. Par exemple, avec des compréhensions de liste:

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

ou avec la commande fonctionnelle filter et les fonctions lambda. (Vous devez tester les deux méthodes et combiner).

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

Je ne sais pas s'il existe une fonction Nice pour cela, mais la façon "manuelle" de le faire n'est pas difficile:

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

je suppose que vous devrez convertir vos listes en ensembles:

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

En utilisant des ensembles, vous pouvez en faire un one-line. Si tu veux:

pour obtenir un jeu de tuples, alors:

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

Ou pour obtenir une liste de tuples, alors:

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

Ou pour obtenir une liste de listes (si vous voulez vraiment), alors:

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

PS: Je lis ici: https://stackoverflow.com/a/10973817/4900095 cette fonction map () n’est pas une façon pythonique de faire les choses.

0
Sukrit Gupta

Ancienne question, mais voici une solution que j'utilise pour renvoyer des éléments uniques qui ne figurent pas dans les deux listes.

J'utilise ceci pour comparer les valeurs renvoyées par une base de données et les valeurs générées par un package d'indexeur de répertoires. Je n'ai pas aimé les autres solutions que j'ai trouvées car beaucoup d'entre elles ne pouvaient pas gérer de manière dynamique les listes non hiérarchiques et les listes imbriquées.

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 est un bon point de départ pour ce que vous recherchez.

Si vous l'appliquez de manière récursive aux deltas, vous devriez être capable de gérer des structures de données imbriquées. Mais cela prendra du travail.

0
btilly