【问题标题】:Understanding nested list comprehension理解嵌套列表理解
【发布时间】:2011-12-24 09:19:38
【问题描述】:

我想了解嵌套列表理解。 下面,我列出了一个列表理解表达式及其 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]

form 可以翻译成下面这样。 (我希望我是正确的)

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)

我在Equivalent for loop expression for complex list comprehension上问过类似的问题
那里给出的答案在了解其内部作用后重建了表单。
我想知道它是如何系统地工作的,以便我可以将这个概念应用于其他略有不同的示例。

【问题讨论】:

  • 旁注:在您的示例中,您可以使用 cols = zip(*rows) 将行放入列中,之后您可以简单地为每一列使用 min(col)max(col):@987654334 @。或者在一条短线上:[(min(c), max(c)) for col in zip(*rows)].
  • 如果您要编写 exp1(x,y) 而不仅仅是 exp1 ,会不会是真的,并提高清晰度?我认为这是隐含的,但想确定一下?
  • @GreenAsJade 好吧,可以,exp1 应该是表达式 1

标签: python nested list-comprehension


【解决方案1】:

确实,你是对的。这在Expressions section in the Python Language Reference中有详细描述。

特别注意多个fors 在单个列表推导中的嵌套顺序,始终是从左到右:

>>> 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 for item in row] for row in matrix] 格式有解释 [[exp for item in row] for row in matrix] 格式。我是否遗漏了那里列出的语法中的某些内容?
  • 你没有遗漏任何东西,但那是因为你的例子没有使用任何更特殊的语法,它只是两个简单的列表推导!第一个[exp for item in row] 将创建一个给定行的列表。 “外部”列表推导将创建一个列表,其中每个项目都是由“内部”列表组合创建的列表,矩阵中的每一行对应一个。
  • 哦。正如您在回答中指出的那样,顺序很重要。而且,我想知道是否有关于库参考的部分讨论 [[list comprehension] list comprehension] 格式的排序。
  • 我知道的文档中没有这样的部分。原因是在列表推导中,为每个项目计算的表达式可以是任何有效的 Python 表达式。在这种情况下,“内部”列表推导式就像任何其他 Python 表达式一样。
  • 哇哇……我是唯一对这种排序感到惊讶的人吗:现在解释为什么宏观级别(在这种情况下是矩阵……)出现在嵌套/微观级别(行级别……)之前可能是为了..
【解决方案2】:

简短的回答是:是的,你的理解是正确的

只有一个问题:在 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 [不幸的名字顺便说一句,因为 sets 是 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!

【讨论】:

    猜你喜欢
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 2021-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多