Manera pitónica de crear unión de todos los valores contenidos en múltiples listas

84

Tengo una lista de listas:

lists = [[1,4,3,2,4], [4,5]]

Quiero aplanar esta lista y eliminar todos los duplicados; o, en otras palabras, aplicar una operación de unión establecida:

desired_result = [1, 2, 3, 4, 5]

¿Cuál es la forma más sencilla de hacer esto?

AJ.
fuente

Respuestas:

152

set.union hace lo que quiere:

>>> results_list = [[1,2,3], [1,2,4]]
>>> results_union = set().union(*results_list)
>>> print(results_union)
set([1, 2, 3, 4])

También puede hacer esto con más de dos listas.

algo
fuente
@sth, gracias por ejemplo, pero cuando lo ejecuto aparece un error: Traceback (última llamada más reciente): File "so_example.py", línea 33, in? results_union = set (). union (* result_lists) TypeError: union () toma exactamente un argumento (3 dados)
AJ.
1
@AJ: De acuerdo con la documentsion ( docs.python.org/library/stdtypes.html#set.union ) union()solo admite múltiples argumentos para Python versión 2.6 o superior. Parece que usa una versión anterior a esa, por lo que probablemente tenga que usar un bucle explícito: total = set(); for x in results_list: total.update(x) (s /; / \ n /)
sth
2
También puede guardar la creación de un conjunto vacío cambiando la segunda línea aresults_union = set.union(*(set(el) for el in results_list))
Noel Evans
1
@ Jean-FrançoisFabre TypeError: descriptor 'union' requires a 'set' object but received a 'list'en Python 3.6 al menos.
Paritosh Singh
1
Si usa set.union(*results_list), está vinculando el descriptor del método manualmente, es decir, enviando el primer elemento de results_listcomo "self". Esto crea algunas restricciones extrañas: 1. no escribe correctamente el pato (ahora el primer elemento debe ser un conjunto o instancia de una subclase de conjunto), y 2. la unión de un vacío results_listserá un error (resultado incorrecto - debería devolver vacío conjunto).
wim
12

Dado que parece estar usando Python 2.5 ( sería bueno mencionar en su Q si necesita una A para las versiones! = 2.6, la producción actual, por cierto ;-) y quiere una lista en lugar de un conjunto como el resultado, recomiendo:

import itertools

...

return list(set(itertools.chain(*result_list)))

itertools es generalmente una excelente manera de trabajar con iteradores (y por lo tanto con muchos tipos de secuencias o colecciones) y le recomiendo que se familiarice con él. itertools.chain, en particular, se documenta aquí .

Alex Martelli
fuente
+1 Un ejemplo perfecto de un buen momento para sumergirse en el maravilloso itertoolspaquete.
gotgenes
@Alex gracias ... edité mi pregunta para especificar la versión y quitarme la culpa por estar tan atrasado en las versiones :) Haré un punto para buscar en itertools, agradezco la sugerencia.
AJ.
@AJ, no tengo la culpa, todos podemos sufrir bajo tales restricciones después de todo (¡pero recuerde especificar en futuras preguntas! -); itertools.chainPor cierto, también funciona bien en Python 2.4.
Alex Martelli
3

También puedes seguir este estilo

In [12]: a = ['Orange and Banana', 'Orange Banana']
In [13]: b = ['Grapes', 'Orange Banana']
In [14]: c = ['Foobanana', 'Orange and Banana']

In [20]: list(set(a) | set(b) | set(c))
Out[20]: ['Orange and Banana', 'Foobanana', 'Orange Banana', 'Grapes']

In [21]: list(set(a) & set(b) | set(c))
Out[21]: ['Orange and Banana', 'Foobanana', 'Orange Banana']    
GrvTyagi
fuente
1

Las uniones no son compatibles con listas, que están ordenadas, pero son compatibles con conjuntos. Echa un vistazo a set.union .

Justin R.
fuente
0

Usé lo siguiente para hacer intersecciones, lo que evita la necesidad de conjuntos.

a, b= [[1,2,3], [1,2]]
s = filter( lambda x: x in b, a)

o,

s = [ x for x in b if x in a ]
Oso
fuente
5
¿Por qué querrías "evitar la necesidad de conjuntos"? Son más rápidos y claros para este propósito. Y su "x en a" realiza una búsqueda lineal de fuerza bruta a través de la lista cada vez que la ejecuta. ¡Qué asco!
Peter Hansen
conjuntos requieren la conversión de tipos, y la velocidad lineal no es malo, a menos que se trata de un gran N.
Oso
3
"Tipo de casting"? ¿En Python? ¿Desde cuando? Los conjuntos son básicamente dictados con solo las claves, y utilizan comparaciones hash e igualdad. Usar "x en a" en una lista también hace una comparación de igualdad. ¿Qué es todo esto sobre el casting de tipos?
Peter Hansen
0

en forma de comprensión:

[*{ j for i in lists for j in i }]

o

[*functools.reduce(lambda x,y: {*x, *y}, lists)]
Cachondo
fuente
-2
desired_result = [x for y in lists for x in y]
Mike G.
fuente