¿Explicación de cómo funciona la comprensión de listas anidadas?

No tengo ningún problema para entender esto:

a = [1,2,3,4] b = [x for x in a] 

Pensé que eso era todo, pero luego encontré este fragmento:

 a = [[1,2],[3,4],[5,6]] b = [x for xs in a for x in xs] 

Lo que hace b = [1,2,3,4,5,6] . El problema es que tengo problemas para entender la syntax en [x for xs in a for x in xs] . ¿Alguien podría explicar cómo funciona?

Ah, las incomprensibles comprensiones “anidadas”. Los bucles se desenrollan en el mismo orden que en la comprensión.

 [leaf for branch in tree for leaf in branch] 

Ayuda a pensar de esta manera.

 for branch in tree: for leaf in branch: yield leaf 

El PEP202 afirma esta syntax con “el último índice que varía más rápido” es “el correcto”, en particular sin una explicación de por qué .

si a = [[1,2],[3,4],[5,6]] , entonces si desenrollamos la lista de comp, obtenemos:

  +----------------a------------------+ | +--xs---+ , +--xs---+ , +--xs---+ | for xs in a | | x , x | | x , x | | x , x | | for x in xs a = [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ] b = [ x for xs in a for x in xs ] == [1,2,3,4,5,6] #a list of just the "x"s 

b = [x for xs in a for x in xs] es similar al siguiente bucle nested.

 b = [] for xs in a: for x in xs: b.append(x) 

Eficazmente:

 ...for xs in a...] 

está iterando sobre su lista principal (exterior) y devolviendo cada uno de sus sublistas a su vez.

 ...for x in xs] 

está iterando sobre cada una de estas sublistas.

Esto puede ser reescrito como:

 b = [] for xs in a: for x in xs: b.append(x) 

Se puede escribir así.

 result = [] for xs in a: for x in xs: result.append(x) 

Puedes leer más sobre esto aquí.

Este es un ejemplo de una comprensión anidada. Piense en a = [[1,2],[3,4],[5,6]] como una matriz de 3 por 2 (matriz = [[1,2], [3,4], [5,6] ]).

  ______ row 1 |1 | 2 | ______ row 2 |3 | 4 | ______ row 3 |5 | 6 | ______ 

La comprensión de la lista que ve es otra forma de obtener todos los elementos de esta matriz en una lista.

Trataré de explicar esto utilizando diferentes variables que, con suerte, tendrán más sentido.

 b = [element for row in matrix for element in row] 

El primer bucle for se repite sobre las filas dentro de la matriz, es decir, [1,2],[3,4],[5,6] . El segundo bucle para itera sobre cada elemento en la lista de 2 elementos.

He escrito un pequeño artículo sobre Comprensión de lista en mi sitio web http://programmathics.com/programming/python/python-list-comprehension-tutorial/ que en realidad cubría un escenario muy similar a esta pregunta. También doy algunos otros ejemplos y explicaciones de la comprensión de la lista de python.

Descargo de responsabilidad: Soy el creador de ese sitio web.

Sí, puede anidar para bucles DENTRO de una lista de comprensión. Incluso puedes anidar si hay declaraciones allí.

 dice_rolls = [] for roll1 in range(1,7): for roll2 in range(1,7): for roll3 in range(1,7): dice_rolls.append((roll1, roll2, roll3)) # becomes dice_rolls = [(roll1, roll2, roll3) for roll1 in range(1, 7) for roll2 in range(1, 7) for roll3 in range(1, 7)] 

Escribí un breve artículo en el medio explicando las comprensiones de la lista y algunas otras cosas geniales que puedes hacer con python, deberías echar un vistazo si estás interesado:)

b = [x para xs en a para x en xs] es igual que:

 b = [] for xs in a: for x in xs: b.append(x) 

Para una mejor comprensión, simplemente vaya de derecha a izquierda y agregue los bucles uno tras otro y, a medida que se crea, la Lista x se convirtió en un elemento de la lista.

Las comprensiones de listas son listas que se generan con un bucle for interno. Son una característica muy común en Python y se parecen a algo como:

[cosa por cosa en lista de cosas]

OK, genial, pero ¿por qué querría usar esto?

Las comprensiones de listas son excelentes para usar cuando se desea ahorrar algo de espacio. También son útiles cuando solo necesita procesar una lista rápidamente para hacer un trabajo repetitivo en esa lista. También son realmente útiles si aprendes sobre progtwigción funcional, pero ese es un tema para un curso posterior (sugerencia de pista).

Pero si todo lo que podría hacer es trabajar directamente a través de una lista, la comprensión de la lista no sería tan útil. Afortunadamente, se pueden utilizar con condiciones.

 a = [[1,2],[3,4],[5,6]] b = [x for xs in a for x in xs] 

Aquí, for xs in a ejecución como un bucle externo y for x in xs como un bucle interno . Y así, se puede escribir como siguiendo

 b = [] for xs in a: for x in xs: b.append(x)