¿Cómo extraer elementos de sublistas en una comprensión de una línea en python?

Actualmente estoy aprendiendo el concepto de comprensión de listas en python. Sin embargo, tengo grandes problemas cuando la lista sobre la que estoy iterando contiene sublistas de igual o diferente duración. Por ejemplo, me gustaría convertir el código para union_set() en una comprensión de una línea:

 def union_set(L): S_union = set() for i in range(len(L)): S_union.update(set(L[i])) return S_union L1 = [1, 2, 3] L2 = [4, 5, 6] L3 = [7, 8, 9] L = [L1, L2, L3] print(L) print(union_set(L)) 

Estoy bastante seguro de que esto debería ser posible (tal vez desempacando de alguna manera el contenido de los sublistas (?)), Pero temo que me esté perdiendo algo aquí. ¿Alguien puede ayudar?

Usando la comprensión de listas, puedes hacer algo como eso:

 >>> L1 = [1, 2, 3] >>> L2 = [4, 5, 6] >>> L3 = [7, 8, 9] >>> L = [L1, L2, L3] >>> s=set([x for y in L for x in y]) >>> s set([1, 2, 3, 4, 5, 6, 7, 8, 9]) 

y está iterando sobre la lista secundaria, mientras que x itera sobre los elementos en y.

Utilice un set vacío y .union it:

 L1 = [1, 2, 3] L2 = [4, 5, 6] L3 = [7, 8, 9] print set().union(L1, L2, L3) 

Utilizado en su código como:

 L = [L1, L2, L3] def union_set(L): return set().union(*L) 

Use * para desempacar y pase los elementos desempaquetados a set.union :

 >>> L = [L1, L2, L3] >>> set.union(*(set(x) for x in L)) set([1, 2, 3, 4, 5, 6, 7, 8, 9]) 

Versiones eficientes usando itertools :

 >>> from itertools import islice >>> set.union(set(L[0]),*islice(L,1,None)) set([1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> from itertools import chain >>> set(chain.from_iterable(L)) set([1, 2, 3, 4, 5, 6, 7, 8, 9]) 

Comparaciones de tiempo:

 >>> L = [L1, L2, L3]*10**5 >>> %timeit set.union(*(set(x) for x in L)) 1 loops, best of 3: 416 ms per loop >>> %timeit set(chain.from_iterable(L)) # winner 1 loops, best of 3: 69.4 ms per loop >>> %timeit set.union(set(L[0]),*islice(L,1,None)) 1 loops, best of 3: 78.6 ms per loop >>> %timeit set().union(*L) 1 loops, best of 3: 105 ms per loop >>> %timeit set(chain(*L)) 1 loops, best of 3: 79.2 ms per loop >>> %timeit s=set([x for y in L for x in y]) 1 loops, best of 3: 151 ms per loop 

Podrías usar itertools.chain como esta

 >>> L1 = [1, 2, 3] >>> L2 = [4, 5, 6] >>> L3 = [7, 8, 9] >>> L = [L1,L2,L3] >>> set(itertools.chain(*L)) set([1, 2, 3, 4, 5, 6, 7, 8, 9]) 

* desempaqueta la lista, y la chain crea una lista de sublistas.