python - for - Doble iteración en la comprensión de la lista
python list comprehension tutorial (8)
En Python puede 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 a y b. Soy consciente de la semántica de bucle anidado 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 interior?
Como ejemplo, si tengo una lista anidada:
a=[[1,2],[3,4]]
cuál sería la expresión de comprensión de la lista para lograr este resultado:
[1,2,3,4]
?? (Por favor, solo haga una lista de respuestas de comprensión, ya que esto es lo que quiero averiguar).
¡Espero que esto ayude a alguien más ya que a,b,x,y
no tienen mucho significado para mí! Supongamos que tiene un texto lleno de oraciones y quiere una matriz 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 la lista como un código de estiramiento horizontal.
Trata de dividirlo en:
# List Comprehension
[word for sentence in text for word in sentence]
Además, puede usar solo 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 incluso podría hacer que sea más (lista) 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 el cual el valor actual se sobrescribe con el elemento actual al que accede, luego la primera x
define lo que queremos volver
Caramba, creo que encontré el guante: no me estaba preocupando lo suficiente sobre qué loop es interno y cuál es externo. La lista de comprensión debería 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 :-). Perdón por el ruido.
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)
Para responder a su pregunta con su propia sugerencia:
>>> [x for b in a for x in b] # Works fine
Mientras pediste respuestas de comprensión de listas, permíteme también señalar la excelente itertools.chain ():
>>> from itertools import chain
>>> list(chain.from_iterable(a))
>>> list(chain(*a)) # If you''re using python < 2.6
Si desea mantener la matriz multidimensional, debe anidar los corchetes de la 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]
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]
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 "<stdin>", line 1, in <module>
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 que se produce se ejecutará primero.
El segundo "problema" de esto es que b
se "filtró" fuera de la lista de comprensión. Después de la primera comprensión exitosa de la lista b == [3, 4]
.