web-dev-qa-db-fra.com

Comprendre la compréhension des listes imbriquées

Je veux comprendre la compréhension des listes imbriquées. Ci-dessous, j'ai énuméré une expression de compréhension de liste et son équivalent pour la boucle for.
Je me demande si ma compréhension est correcte à ce sujet.

Par exemple,

[(min([row[i] for row in rows]),max([row[i] for row in rows])) 
for i in range(len(rows[0]))]

est équivalent à

result=[]
for i in range(len(rows[0])):
  innerResult=[]
  for row in rows:
    innerResult.append(row[i])
  innerResult2=[]
  for row in rows:
    innerResult2.append(row[i])
  Tuple=(min(innerResult), max(innerResult2))
  result.append(Tuple)

Si je peux généraliser, je suppose

[exp2([exp1 for x in xSet]) for y in ySet]

formulaire peut être traduit à la suivante. (J'espère avoir raison sur ce point)

result=[]
for y in ySet:
  innerResult =[]
  for x in xSet:
    innerResult.append(exp1)
  exp2Result = exp2(innerResult)
  result.append(exp2Result)

Pour un cas plus simple,

[exp1 for x in xSet for y in ySet] 

est égal à

result=[] 
for x in xSet:
  for y in ySet: 
    result.append(exp1)

tandis que,

[[exp1 for x in xSet] for y in ySet]

est égal à

result=[]
for y in ySet:
  innerResult=[]
  for x in xSet:
    innerResult.append(exp1)
  result.append(innerResult)

J'ai posé une question similaire sur équivalent pour l'expression de boucle pour la compréhension de liste complexe
Les réponses données reconstruisent la forme après avoir compris ce qu’elle fait en interne.
J'aimerais savoir comment cela fonctionne systématiquement afin de pouvoir appliquer le concept à d'autres exemples légèrement différents.

71
eugene

La réponse courte est: oui, votre compréhension est correcte .

Il n’ya qu’un inconvénient: la façon dont vous utilisez normalement la compréhension de liste imbriquée dans python) consiste à opérer sur des tableaux multidimensionnels.

Un exemple typique est lorsque vous utilisez des matrices:

>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [[el - 1 for el in row] for row in matrix]
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]

Comme vous pouvez le voir, "l'imbrication" fonctionne en opérant sur chaque dimension de la matrice.

Dans les exemples que vous avez fournis, il semble que ySet [nom malheureux btw, comme sets sont l'un des types fournis avec python] n'est qu'un compteur générique, ce qui rend un peu plus difficile de suivre ce qui se passe sous le capot.

Quant à votre premier exemple:

>>> rows = ([1, 2, 3], [10, 20, 30])
>>> [(min([row[i] for row in rows]),max([row[i] for row in rows])) for i in range(len(rows[0]))]
[(1, 10), (2, 20), (3, 30)]

Vous voudrez peut-être examiner la fonction intégrée Zip :

>>> Zip(rows[0], rows[1])
[(1, 10), (2, 20), (3, 30)]

ou pour un maximum de brièveté et d'élégance:

>>> Zip(*rows)
[(1, 10), (2, 20), (3, 30)]

HTH!

70
mac

En effet, vous avez raison. Ceci est décrit en détail dans la section Section Expressions de la Python .

Notez en particulier l'ordre d'imbrication de plusieurs fors dans une liste à comprendre, qui est toujours de gauche à droite:

>>> matrix = [[1, 2], [3, 4]]
>>> [item for item in row for row in matrix] # oops!
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    [item for item in row for row in matrix]
NameError: name 'row' is not defined
>>> [item for row in matrix for item in row] # nesting is in left-to-right order
[1, 2, 3, 4]
72
taleinat