Dans Python vous pouvez avoir plusieurs itérateurs dans une liste de compréhension, comme
[(x,y) for x in a for y in b]
pour certaines séquences appropriées a et b. Je suis conscient de la sémantique de boucle imbriquée de la compréhension de liste de Python.
Ma question est la suivante: un itérateur dans la compréhension peut-il se référer à l'autre? En d'autres termes: Pourrais-je avoir quelque chose comme ceci:
[x for x in a for a in b]
où la valeur actuelle de la boucle externe est l'itérateur de la boucle interne?
Par exemple, si j'ai une liste imbriquée:
a=[[1,2],[3,4]]
que serait l'expression de compréhension de liste pour atteindre ce résultat:
[1,2,3,4]
?? (Veuillez ne lister que les réponses de compréhension, puisque c'est ce que je veux savoir).
Eh bien, je suppose que j'ai trouvé la réponse: je ne faisais pas assez attention à quelle boucle est intérieure et quelle est extérieure. La liste de compréhension devrait être comme:
[x for b in a for x in b]
pour obtenir le résultat souhaité, et oui, une valeur actuelle peut être l'itérateur de la boucle suivante.
Pour répondre à votre question avec votre propre suggestion:
>>> [x for b in a for x in b] # Works fine
Pendant que vous demandiez des réponses sur la compréhension de la liste, permettez-moi également de souligner l'excellent itertools.chain ():
>>> from itertools import chain
>>> list(chain.from_iterable(a))
>>> list(chain(*a)) # If you're using python < 2.6
J'espère que cela aide quelqu'un d'autre depuis a,b,x,y
n'a pas beaucoup de sens pour moi! Supposons que vous avez un texte plein de phrases et que vous voulez un tableau de mots.
# Without list comprehension
list_of_words = []
for sentence in text:
for Word in sentence:
list_of_words.append(Word)
return list_of_words
J'aime penser que la compréhension de liste est un code d'étirement horizontal.
Essayez de le diviser en:
# List Comprehension
[Word for sentence in text for Word in sentence]
L'ordre des itérateurs peut sembler contre-intuitif.
Prenons par exemple: [str(x) for i in range(3) for x in foo(i)]
Décomposons le:
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 a déjà ajouté une bonne réponse, mais je veux montrer ce qui se passe:
>>> 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]
Je suppose que Python analyse la compréhension de la liste de gauche à droite. Cela signifie que la première boucle for
qui se produit sera exécutée en premier.
Le deuxième "problème" de ceci est que b
obtient "une fuite" hors de la compréhension de la liste. Après la première compréhension de liste réussie b == [3, 4]
.
Si vous souhaitez conserver le tableau multidimensionnel, vous devez imbriquer les crochets du tableau. voir exemple ci-dessous où l'on est ajouté à chaque élément.
>>> 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]
De plus, vous pouvez utiliser exactement la même variable pour le membre de la liste de saisie auquel on accède actuellement et pour l'élément à l'intérieur de ce membre. Cependant, cela pourrait même le rendre plus (liste) incompréhensible.
input = [[1, 2], [3, 4]]
[x for x in input for x in x]
Première for x in input
est évalué, menant à une liste de membres de l’entrée, puis, Python parcourt la deuxième partie for x in x
pendant laquelle la valeur x est écrasée par l'élément actuel auquel elle accède, le premier x
définit ce que nous voulons retourner.
Je pense que c'est plus facile à comprendre
[row[i] for row in a for i in range(len(a))]
result: [1, 2, 3, 4]