了解嵌套列表理解


74

我想了解嵌套列表的理解。下面,我列出了一个列表理解表达式及其for循环等效项。
我不知道我的理解是否正确。

例如,

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

相当于

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)

如果可以概括一下,我猜

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

表格可以翻译为以下内容。(我希望我是对的)

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

对于更简单的情况,

[exp1 for x in xSet for y in ySet] 

等于

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

而,

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

等于

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

我问了一个类似的问题,即用于复杂列表理解
循环表达式的等效项。那里给出的答案是在理解了表单内部的内容之后重新构造了表单。
我想知道它是如何系统地工作的,因此我可以将该概念应用于其他稍有不同的示例。


3
附注:在您的例子,你可能会用行转换成列cols = zip(*rows),在这之后,你可以简单地使用min(col),并max(col)为每列:[(min(c), max(c)) for c in cols]。或短短一行:[(min(c), max(c)) for col in zip(*rows)]
taleinat 2011年

如果您要编写exp1(x,y)而不是exp1,那会是正确的并提高了清晰度吗?我认为这是暗含的,但想确定吗?
GreenAsJade '16

@GreenAsJade好吧,是的,这行得通,exp1本来应该是expression1
eugene

Answers:


74

简短的答案是:是的,您的理解正确

有一个陷阱:在python代码中通常使用嵌套列表理解的方法是对多维数组进行操作。

一个典型的例子是当您对矩阵进行运算时:

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

如您所见,“嵌套”通过在矩阵的每个维度上进行操作而起作用。

在您提供的示例中,ySet[不幸的名字btw,因为集合是python提供的类型之一]只是一个通用计数器,这使得了解幕后情况变得有些困难。

至于第一个示例:

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

您可能希望研究zip内置功能:

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

或为了最大程度地简洁和优雅:

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

HTH!


76

确实,你是对的。《 Python语言参考》中的“表达式”部分对此进行了详细描述。

特别注意for单个列表推导中几个s的嵌套顺序,该顺序始终从左到右:

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

我看了链接。确实,有[行中项目的矩阵中行的项目]的解释,但找不到[矩阵中行的[[行中项目的exp]的解释]格式。我在这里列出的语法中缺少什么吗?
尤金

您什么都不会丢失,但这是因为您的示例没有使用任何更特殊的语法,这只是两个简单的列表推导!第一个[exp for item in row]将创建给定行的列表。“外部”列表理解将创建一个列表,其中每个项目都是由“内部” list-comp创建的列表,矩阵中的每一行一个。
taleinat 2011年

1
哦。正如您在回答中指出的那样,顺序很重要。而且,我想知道是否有关于库参考的部分讨论[[列表理解]列表理解]格式的顺序。
尤金

3
我所知道的文档中没有此类部分。原因是在列表理解中,为每个项目评估的表达式可以是任何有效的Python表达式。在这种情况下,“内部”列表理解与任何其他Python表达式一样。
taleinat 2011年

2
哇whee ..我是唯一一个通过此排序惊讶:为什么现在宏观层面(矩阵在这种情况下..)嵌套/微观层面之前发生的解释(行级..)可能是为了..
StephenBoesch
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.