web-dev-qa-db-fra.com

Double itération dans la compréhension de la liste

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).

189
ThomasH

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.

108
ThomasH

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
143
Cide

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]
122
Skam

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)
40
Dima Tisnek

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].

18
Martin Thoma

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]
8
steven

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.

3
simP

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]
3
Miao Li