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

时间:2013-12-17 16:15:04

标签: 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]中的语法时遇到了麻烦,有人能解释它是如何工作的吗?

13 个答案:

答案 0 :(得分:55)

啊,难以理解的“嵌套”理解。循环以与理解中相同的顺序展开。

[leaf for branch in tree for leaf in branch]

这样就可以想到它。

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

PEP202声明这种语法,“最后一个索引变化最快”是“正确的一个”,特别是没有解释为什么

答案 1 :(得分:23)

如果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

答案 2 :(得分:9)

b = [x for xs in a for x in xs]类似于嵌套循环。

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

答案 3 :(得分:4)

它可以像这样写成

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

您可以阅读更多相关信息here

答案 4 :(得分:4)

有效:

...for xs in a...]

正在遍历主(外部)列表并依次返回每个子列表。

...for x in xs]

然后迭代这些子列表中的每一个。

这可以重写为:

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

答案 5 :(得分:3)

这是嵌套理解的一个例子。将a = [[1,2],[3,4],[5,6]]视为3乘2矩阵(矩阵= [[1,2],[3,4],[5,6]])。

       ______
row 1 |1 | 2 |
       ______
row 2 |3 | 4 |
       ______
row 3 |5 | 6 |
       ______

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

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

b = [element for row in matrix for element in row]

第一个for循环迭代矩阵内的行,即[1,2],[3,4],[5,6]。第二个for循环遍历2个元素列表中的每个元素。

我在我的网站http://programmathics.com/programming/python/python-list-comprehension-tutorial/上写了一篇关于列表理解的小文章,其实际涵盖了与此问题截然不同的场景。我还给出了一些python列表理解的例子和解释。

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

答案 6 :(得分:3)

这是我最记得的方式: (伪代码,但是具有这种类型的模式)

[(x,y,z) (loop 1) (loop 2) (loop 3)]

最右边的循环(循环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)]

例如:

[(x,y,z)    for x in range(3)    for y in range(3)    for z in range(3)    if x == y == z]

具有这种类型的结构:

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



答案 7 :(得分:1)

是的,您可以嵌套列表理解的INSIDE循环。你甚至可以在那里嵌套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)]

我写了a short article on medium解释列表理解以及你可以用python做的其他一些很酷的事情,你应该看看你是否感兴趣:)

答案 8 :(得分:1)

您要的是嵌套列表。

让我尝试逐步解决这个问题,涵盖以下主题:

  • 用于循环
  • 列表理解
  • 嵌套用于循环和列表理解

用于循环

您有以下列表: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)

使用列表理解,您可以做完全相同的事情(这更像pythonic)。

列表理解

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

new_list = [lst_item for lst_item in lst]

您以这种方式阅读:对于lst_item中的每个lst,将lst_item添加到new_list

嵌套列表

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

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

假设您有一个嵌套列表:nested_list = [[0,1,2], [3,4,5], [6,7,8]],并且想将其转换为扁平化列表,例如:flattened list = [0,1,2,3,4,5,6,7,8]

如果您使用与以前相同的for循环,则不会得到它。

flattened_list = []
for list_item in nested_list:
    flattened_list.append(list_item)

为什么?因为每个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]

您需要一种进入子列表并将每个子列表项添加到flattened list的方法。

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

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

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)

让我们大声朗读这段代码。

for sublist in nested_list:每个子列表是[0,1,2][3,4,5][6,7,8]。在第一个循环的第一次迭代中,我们进入[0,1,2]内部。

for item in sublist: [0,1,2]的第一项是0,它附加到flattened_list上。然后是1,最后是2

到目前为止flattened_list[0,1,2]

我们完成了第二个循环的最后一个迭代,因此我们转到第一个循环的下一个迭代。我们进入[3,4,5]

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

如何使用列表推导?

列表理解解决方案。

flattened_list = [item for sublist in nested_list for item in sublist]

您这样读:将item中每个sublist中的每个nested_list中添加。

它更简洁,但是如果您有很多层,可能会变得更加难以阅读。

让我们一起看

#for loop
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)

----------------------------------------------------------------------

#list comprehension
flattened_list = [item for sublist in nested_list for item in sublist]

您将在迭代的更多层中添加更多for x in y

答案 9 :(得分:0)

b = [x表示x中x表示的xs]与:

相同
b = []
for xs in a:
    for x in xs:
        b.append(x)

为了更好地理解,只需从右到左依次添加for循环,并创建List x成为列表元素。

答案 10 :(得分:0)

列表推导是使用内部for循环生成自己的列表。它们是Python中非常常见的功能,它们看起来像:

[list_of_things中的东西]

好的,很好,但为什么我要使用它?

当您想节省一些空间时,列表理解很有用。当您只需要快速处理列表以在该列表上执行重复性工作时,它们也很方便。如果您了解函数式编程,它们也非常有用,但这是后期课程的主题(提示提示)。

但是,如果您所能做的就是直接通过列表,那么列表推导就不会那么有用了。值得庆幸的是,它们可以用于条件。

答案 11 :(得分:0)

英语语法:

b = "a list of 'specific items' taken from 'what loop?' "
b = [x for xs in a for x in xs]

x 是具体的项目
for xs in a for x in xs 是循环

答案 12 :(得分:-1)

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

在这里,for xs in a表现为外循环,而for x in xs表现为内循环。因此,它可以像下面这样写:

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