Python 解释嵌套列表理解是如何工作的?

Python 解释嵌套列表理解是如何工作的?,python,list,Python,List,我完全理解这一点: a = [1,2,3,4] b = [x for x in a] 我以为就这些,但后来我发现了这个片段: a = [[1,2],[3,4],[5,6]] b = [x for xs in a for x in xs] 这使得b=[1,2,3,4,5,6]。问题是我很难理解[x for xs in a for x in xs]中的语法,有人能解释一下它是如何工作的吗 可以这样写 result = [] for xs in a: for x in xs:

我完全理解这一点:

a = [1,2,3,4]
b = [x for x in a]
我以为就这些,但后来我发现了这个片段:

a = [[1,2],[3,4],[5,6]]
b = [x for xs in a for x in xs]

这使得
b=[1,2,3,4,5,6]
。问题是我很难理解
[x for xs in a for x in xs]
中的语法,有人能解释一下它是如何工作的吗

可以这样写

result = []
for xs in a:
    for x in xs:
        result.append(x)

您可以阅读更多有关它的信息

b=[x代表xs,x代表xs]
类似于下面的嵌套循环

b = []
for xs in a:
   for x in xs:
       b.append(x)
实际上:

...for xs in a...]
正在迭代主(外部)列表并依次返回每个子列表

...for x in xs]
然后在每个子列表上迭代

这可以重写为:

b = []
for xs in a:
    for x in xs:
        b.append(x)
啊,难以理解的“嵌套”理解。循环的展开顺序与理解中的相同

[leaf for branch in tree for leaf in branch]
这样想很有帮助

for branch in tree:
    for leaf in branch:
        yield leaf

声明说,使用“最后一个索引变化最快”的语法是“正确的”,特别是没有解释原因

如果
a=[[1,2],[3,4],[5,6]]
,那么如果我们展开该列表comp,我们得到:

      +----------------a------------------+ 
      | +--xs---+ , +--xs---+ , +--xs---+ | for xs in a
      | | x , x |   | x , x |   | x , x | | for x in xs
a  =  [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ]
b  =  [ x for xs in a for x in xs ] == [1,2,3,4,5,6] #a list of just the "x"s

这是嵌套理解的一个示例。把a=[[1,2],[3,4],[5,6]]想象成一个3乘2的矩阵(矩阵=[[1,2],[3,4],[5,6]])

您看到的列表理解是将此矩阵中的所有元素放入列表的另一种方法

我将尝试用不同的变量来解释这一点,希望这会更有意义

b = [element for row in matrix for element in row]
第一个for循环迭代矩阵中的行,即
[1,2]、[3,4]、[5,6]
。第二个for循环迭代2个元素列表中的每个元素

我在我的网站上写了一篇关于列表理解的小文章,实际上涵盖了与这个问题非常相似的场景。我还提供了一些python列表理解的其他示例和解释


免责声明:我是该网站的创建者。

是的,您可以在列表中嵌套for循环。您甚至可以在其中嵌套if语句

dice_rolls = []
for roll1 in range(1,7):
    for roll2 in range(1,7):
        for roll3 in range(1,7):
            dice_rolls.append((roll1, roll2, roll3))

# becomes

dice_rolls = [(roll1, roll2, roll3) for roll1 in range(1, 7) for roll2 in range(1, 7) 
              for roll3 in range(1, 7)]

我写了一篇文章,解释了列表理解和其他一些可以用python做的很酷的事情,如果你感兴趣的话,你应该看看:)

以下是我对它最好的记忆: (伪代码,但具有这种类型的模式)

其中最右边的回路(回路3)是最里面的回路

[(x,y,z)    for x in range(3)    for y in range(3)    for z in range(3)]
其结构如下:

for x in range(3):
    for y in range(3):
        for z in range(3):
            print((x,y,z))
编辑我想添加另一个图案:

[(result) (loop 1) (loop 2) (loop 3) (condition)]
例:

具有这种类型的结构:

for x in range(3):
    for y in range(3):
        for z in range(3):
            if x == y == z:
                print((x,y,z))




您要求的是嵌套列表

让我尝试一步一步地回答这个问题,涵盖以下主题:

  • For循环
  • 列表理解
  • 嵌套for循环和列表理解

For循环 您有以下列表:
lst=[0,1,2,3,4,5,6,7,8]
,您希望一次迭代一个列表项,并将它们添加到新列表中。您可以执行一个简单的for循环:

lst = [0,1,2,3,4,5,6,7,8]
new_list = []

for lst_item in lst:
    new_list.append(lst_item)
你可以用列表理解做完全相同的事情(它更像python)

列表理解 列表理解是创建列表的一种(*有时)简单而优雅的方法

new_list = [lst_item for lst_item in lst]
您可以这样理解:对于
lst
中的每个
lst\u项目
,将
lst\u项目
添加到
新列表

嵌套列表 什么是嵌套列表? 一个简单的定义:它是一个包含子列表的列表。您在另一个列表中有列表

*根据您与谁交谈,嵌套列表是列表理解比常规for循环更难阅读的情况之一

假设您有一个嵌套列表:
nested_list=[[0,1,2],[3,4,5],[6,7,8]
,您希望将其转换为一个类似这样的展开列表:
展开列表=[0,1,2,3,4,5,6,7,8]

如果你像以前一样对循环使用相同的方法,你就不会得到它

flattened_list = []
for list_item in nested_list:
    flattened_list.append(list_item)
为什么??因为每个
列表项实际上都是一个子列表。在第一次迭代中,您得到
[0,1,2]
,然后是
[3,4,5]
,最后是
[6,7,8]

您可以这样检查:

nested_list[0] == [0, 1, 2]
nested_list[1] == [3, 4, 5]
nested_list[2] == [6, 7, 8]
您需要一种方法进入子列表并将每个子列表项添加到展开列表中

如何?
您添加了一个额外的迭代层。实际上,为每层子列表添加一个

在上面的示例中,您有两个层

for循环解决方案。

nested_list = [[0,1,2], [3,4,5], [6,7,8]]

flattened_list = []
for sublist in nested_list:
    for item in sublist:
        flattened_list.append(item)
flattened_list = [item for sublist in nested_list for item in sublist]
让我们大声朗读这段代码

对于嵌套列表中的子列表:
每个子列表是
[0,1,2]
[3,4,5]
[6,7,8]
。在第一个循环的第一次迭代中,我们进入
[0,1,2]

对于子列表中的项:
[0,1,2]
的第一项是
0
,它被附加到
列表中。然后是
1
,最后是
2

在此之前,列表是
[0,1,2]

我们完成了第二个循环的最后一次迭代,所以我们进入第一个循环的下一次迭代。我们进入
[3,4,5]

然后,我们转到该子列表的每个项目,并将其附加到
platten\u列表
。然后我们进行下一次迭代,以此类推

如何使用列表理解来实现这一点

列表理解解决方案。

nested_list = [[0,1,2], [3,4,5], [6,7,8]]

flattened_list = []
for sublist in nested_list:
    for item in sublist:
        flattened_list.append(item)
flattened_list = [item for sublist in nested_list for item in sublist]
您的阅读方式如下:从每个
子列表添加每个

它更简洁,但如果你有很多层,它可能会变得更难阅读

让我们一起来看看 迭代的层数越多,您将为y中的x添加更多的


2021年4月编辑

可以使用Numpy展平嵌套列表。从技术上讲,Numpy中的术语是“数组”

对于一个小的列表来说,这是一种过分的做法,但是如果你正在处理列表中的数百万个数字,你可能需要Numpy

从努比家。我们有一套
公寓

b = np.array(
[
  [ 0,  1,  2,  3],
  [10, 11, 12, 13],
  [20, 21, 22, 23],
  [30, 31, 32, 33],
  [40, 41, 42, 43]
]
)

for element in b.flat:
    print(element)

0
1
2
...
41
42
43
英语语法:

b = "a list of 'specific items' taken from 'what loop?' "
b = [x for xs in a for x in xs]
x
是特定项目
for x in a for x in xs
是它的工作循环

b = np.array(
[
  [ 0,  1,  2,  3],
  [10, 11, 12, 13],
  [20, 21, 22, 23],
  [30, 31, 32, 33],
  [40, 41, 42, 43]
]
)

for element in b.flat:
    print(element)

0
1
2
...
41
42
43
b = "a list of 'specific items' taken from 'what loop?' "
b = [x for xs in a for x in xs]