【问题标题】:Idiom for flattening a shallow nested list: how does it work?扁平化浅嵌套列表的成语:它是如何工作的?
【发布时间】:2012-09-17 03:24:23
【问题描述】:

我在我正在处理的模块中发现了这段代码:

l = opaque_function()
thingys = [x for y in l for x in y]

我看不懂。通过实验,我能够确定它正在展平一个 2 级嵌套列表,但语法对我来说仍然是不透明的。它显然省略了一些可选的括号。

>>> l = [[1,2],[3,4]]
>>> [x for y in l for x in y]
[1, 2, 3, 4]

我的眼睛想将其解析为:[x for y in [l for x in y] ][ [x for y in l] for x in y ],但由于未定义 y,这两个都失败了。

我应该如何阅读这篇文章?

(我怀疑当这被解释时我会感到非常尴尬。)

【问题讨论】:

标签: python


【解决方案1】:

这曾经让我很困惑。你应该像嵌套循环一样阅读它:

new_list = []
for y in l:
    for x in y:
        new_list.append(x)

变成

for y in l for x in y [do] new_list.append(x)

变成

[x for y in l for x in y]

【讨论】:

    【解决方案2】:

    来自list displays 文档:

    提供列表解析时,它由一个表达式组成,后跟至少一个 for 子句和零个或多个 forif 子句。在这种情况下,新列表的元素是通过将每个 forif 子句视为一个块、从左到右嵌套并在每次到达最里面的块。

    因此,您的表达式可以重写为:

    thingys = []
    for y in l:
        for x in y:
            thingys.append(x)
    

    【讨论】:

    • 哇,我不知道允许多个for 子句。在这里我以为我是当地的python专家。谢谢。
    【解决方案3】:

    你应该这样理解:

    for y in l:
        for x in y:
            yield x
    

    这是生成器版本,但所有推导式都有相同的基本语法:虽然 x 放在前面,但表达式的其余部分仍然从左到右读取。一开始我也对此感到困惑,以为它会反过来,但是一旦添加了过滤表达式,它就有意义了:

    >>> l = [[1,2,3,4,5], [1,"foo","bar"], [2,3]]
    >>> [x for y in l
    ...    if len(y) < 4
    ...    for x in y
    ...    if isinstance(x, int)]
    [1, 2, 3]
    

    现在想象一下必须把整个事情倒过来写:

    [x if isinstance(x, int)
       for x in y
       if len(y) < 4
       for y in l]
    

    即使是经验丰富的 Prolog 程序员也会感到困惑,更不用说维护 Python 解析器的人了 :)

    当前语法也匹配 Haskell 中的语法,这首先激发了列表推导。

    【讨论】:

      【解决方案4】:
      lis=[x for y in l for x in y] is Equivalent to:
      
      
      lis=[]
      for y in l:
         for x in y:
            lis.append(x)
      

      【讨论】:

        猜你喜欢
        • 2017-12-01
        • 1970-01-01
        • 2017-03-19
        • 1970-01-01
        • 2014-10-29
        • 2020-07-12
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多