una palabra misma metodos llenar listas lista eliminar elementos comparar buscar arreglos agregar python list compare set tuples

palabra - ¿Cómo comparar una lista de listas/conjuntos en python?



llenar una lista en python (7)

¿Cuál es la forma más fácil de comparar las 2 listas / conjuntos y generar las diferencias? ¿Hay funciones integradas que me ayuden a comparar listas / conjuntos anidados?

Entradas:

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

Rendimiento esperado:

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


Así que quieres la diferencia entre dos listas de artículos.

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

Primero, convertiría cada lista de listas en una lista de tuplas, de modo que las tuplas son hashables (las listas no lo son) para que pueda convertir su lista de tuplas en un conjunto de tuplas:

first_tuple_list = [tuple(lst) for lst in first_list] secnd_tuple_list = [tuple(lst) for lst in secnd_list]

Entonces puedes hacer sets:

first_set = set(first_tuple_list) secnd_set = set(secnd_tuple_list)

EDITAR (sugerido por sdolan): Podrías haber realizado los dos últimos pasos para cada lista en una sola línea:

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

Nota: map es un comando de programación funcional que aplica la función en el primer argumento (en este caso, la función de tuple ) a cada elemento en el segundo argumento (que en nuestro caso es una lista de listas).

y encuentra la diferencia simétrica entre los conjuntos:

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

Note que first_set ^ secnd_set es equivalente a symmetric_difference .

Además, si no desea utilizar conjuntos (por ejemplo, usar Python 2.2), es bastante sencillo hacerlo. Por ejemplo, con listas de comprensión:

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

o con el comando funcional de filter y las funciones lambda . (Hay que probar ambas formas y combinar).

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


Mediante el uso de conjuntos de comprensión, puede hacer que sea de una sola línea. Si tu quieres:

para obtener un conjunto de tuplas, entonces:

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

O para obtener una lista de tuplas, entonces:

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

O para obtener una lista de listas (si realmente quieres), entonces:

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

PD: Leí aquí: https://.com/a/10973817/4900095 que la función map () no es una forma pitónica de hacer las cosas.


No estoy seguro de si hay una buena función para esto, pero la forma "manual" de hacerlo no es difícil:

differences = [] for list in firstList: if list not in secondList: differences.append(list)


Pregunta antigua, pero aquí hay una solución que utilizo para devolver elementos únicos que no se encuentran en ambas listas.

Lo uso para comparar los valores devueltos de una base de datos y los valores generados por un paquete de rastreador de directorios. No me gustaron las otras soluciones que encontré porque muchas de ellas no podían manejar dinámicamente las listas planas y las listas anidadas.

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


Supongo que tendrás que convertir tus listas a conjuntos:

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


http://docs.python.org/library/difflib.html es un buen punto de partida para lo que está buscando.

Si lo aplica recursivamente a los deltas, debería poder manejar estructuras de datos anidadas. Pero tomará algo de trabajo.


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