En Python puedes tener múltiples iteradores en una lista de comprensión, como
[(x,y) for x in a for y in b]
para algunas secuencias adecuadas ay b. Soy consciente de la semántica de bucle nested de las listas de comprensión de Python.
Mi pregunta es: ¿Puede un iterador en la comprensión referirse al otro? En otras palabras: ¿Podría tener algo como esto:
[x for x in a for a in b]
donde el valor actual del bucle externo es el iterador del interno?
Como ejemplo, si tengo una lista anidada:
a=[[1,2],[3,4]]
¿Cuál sería la expresión de comprensión de lista para lograr este resultado?
[1,2,3,4]
?? (Por favor, solo enumere las respuestas de comprensión, ya que esto es lo que quiero averiguar).
Para responder a su pregunta con su propia sugerencia:
>>> [x for b in a for x in b] # Works fine
Mientras que usted pidió respuestas de comprensión de lista, permítame también señalar el excelente itertools.chain ():
>>> from itertools import chain >>> list(chain.from_iterable(a)) >>> list(chain(*a)) # If you're using python < 2.6
Caramba, creo que encontré la respuesta: no estaba cuidando lo suficiente sobre qué bucle es interno y cuál es externo. La lista de comprensión debe ser como:
[x for b in a for x in b]
para obtener el resultado deseado, y sí, un valor actual puede ser el iterador para el siguiente ciclo.
¡Espero que esto ayude a alguien más ya que a,b,x,y
no tienen mucho significado para mí! Supongamos que tienes un texto lleno de oraciones y quieres una serie de palabras.
# Without list comprehension list_of_words = [] for sentence in text: for word in sentence: list_of_words.append(word) return list_of_words
Me gusta pensar en la comprensión de listas como un código de estiramiento horizontal.
Intenta dividirlo en:
# List Comprehension [word for sentence in text for word in sentence]
El orden de los iteradores puede parecer contraintuitivo.
Tomemos por ejemplo: [str(x) for i in range(3) for x in foo(i)]
Vamos a descomponerlo:
def foo(i): return i, i + 0.5 [str(x) for i in range(3) for x in foo(i) ] # is same as for i in range(3): for x in foo(i): yield str(x)
ThomasH ya ha agregado una buena respuesta, pero quiero mostrar lo que sucede:
>>> a = [[1, 2], [3, 4]] >>> [x for x in b for b in a] Traceback (most recent call last): File "", line 1, in NameError: name 'b' is not defined >>> [x for b in a for x in b] [1, 2, 3, 4] >>> [x for x in b for b in a] [3, 3, 4, 4]
Supongo que Python analiza la lista de comprensión de izquierda a derecha. Esto significa que el primer bucle for
que se produce se ejecutará primero.
El segundo “problema” de esto es que b
se “filtra” fuera de la lista de comprensión. Después de la primera comprensión exitosa de la lista b == [3, 4]
.
Si desea mantener la matriz multidimensional, debe anidar los soportes de matriz. vea el ejemplo a continuación donde se agrega uno a cada elemento.
>>> a = [[1, 2], [3, 4]] >>> [[col +1 for col in row] for row in a] [[2, 3], [4, 5]] >>> [col +1 for row in a for col in row] [2, 3, 4, 5]
Además, puede usar la misma variable para el miembro de la lista de entrada a la que se accede actualmente y para el elemento dentro de este miembro. Sin embargo, esto podría incluso hacer que sea (lista) más incomprensible.
input = [[1, 2], [3, 4]] [x for x in input for x in x]
Primero se evalúa la for x in input
, lo que lleva a una lista de miembros de la entrada, luego, Python recorre la segunda parte for x in x
durante la cual el valor actual se sobrescribe con el elemento actual al que está accediendo, luego la primera x
define Lo que queremos volver.
Siento que esto es más fácil de entender
[row[i] for row in a for i in range(len(a))] result: [1, 2, 3, 4]