72 votes

La compréhension de liste imbriquée compréhension

Je veux comprendre la liste imbriquée compréhension. Ci-dessous, j'ai énuméré une liste en compréhension de l'expression et de leur boucle équivalent.
Je me demande si ma compréhension est correcte sur ceux-ci.

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 peut généraliser, je suppose

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

formulaire peut être traduit de la manière suivante. (J'espère que je suis correct sur ce sujet)

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

Pour les 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)

considérant 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 un équivalent pour la boucle de l'expression complexe de compréhension de liste
Les réponses données, il y reconstruire la forme après la compréhension de ce qu'il fait à l'interne.
Je voudrais savoir comment il fonctionne systématiquement afin que je puisse appliquer le concept à d'autres légèrement différents exemples.

72voto

taleinat Points 2525

En effet, vous avez raison. Ceci est décrit en détail dans les Expressions dans la section de Référence au Langage Python.

Notez en particulier l'ordre d'imbrication de plusieurs fors dans une seule liste de compréhension, ce 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]

71voto

mac Points 16282

La réponse courte est: oui, vous avez raison de votre compréhension.

Il n'y a qu'un hic: la façon dont vous utilisez habituellement imbriquée compréhension de liste dans le code python est de fonctionner sur les tableaux multidimensionnels.

Un exemple typique est lorsque vous opérez sur 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 le "imbrication" des œuvres de l'exploitation sur chacune des dimensions de la matrice.

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

Comme pour 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 pourriez vouloir regarder dans le zip intégré dans la fonction:

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

ou pour un maximum de concision et l'élégance:

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

HTH!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X