如何从列表中生成一个简单的列表?

  • 问题:
  • 我想知道在Python中是否有一种快捷方式可以从列表列表中创建一个简单的列表

    我可以在for循环中完成,但也许有一些很酷的“一行程序”?我用reduce()尝试过,但是我得到了一个错误

    编码

    l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
    reduce(lambda x, y: x.extend(y), l)

    错误消息

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 1, in <lambda>
    AttributeError: 'NoneType' object has no attribute 'extend'

  • 答案:
  • 给出一个列表列表l

    flat_list=[子列表中的项对应子列表中的项]

    也就是说:

    flat_list = []
    for sublist in l:
    for item in sublist:
    flat_list.append(item)

    比目前发布的捷径还快。(l是要展开的列表。)

    下面是相应的函数:

    flatten = lambda l: [item for sublist in l for item in sublist]

    作为证据,您可以使用标准库中的timeit模块:

    $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
    10000 loops, best of 3: 143 usec per loop
    $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
    1000 loops, best of 3: 969 usec per loop
    $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
    1000 loops, best of 3: 1.1 msec per loop

    说明:基于+的快捷方式(包括在sum中的隐含用法)是,当有L个子列表时,O(L**2)——随着中间结果列表越来越长,每一步都会分配一个新的中间结果列表对象,上一个中间结果中的所有项目都必须被复制(以及在最后添加一些新的项目)。因此,为了简单起见,并且没有实际的通用性损失,假设每个I项都有L个子列表:第一个I项被来回复制L-1次,第二个I项被复制L-2次,依此类推;总拷贝数是I乘以x的总和,对于从1到L的x,即,I*(L**2)/2

    列表理解只生成一个列表,一次,并将每个项目(从其原始居住地复制到结果列表)也只复制一次