一尘不染

如何从列表列表中制作平面列表

javascript

是否有从 Python 中的列表列表中制作简单列表的快捷方式?

我可以for循环进行,但是有没有一些很酷的“单线”?

我试过functools.reduce()

from functools import 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'

阅读 187

收藏
2022-01-09

共1个答案

一尘不染

给定一个列表列表t

flat_list = [item for sublist in t for item in sublist]

意思是:

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

比迄今为止发布的快捷方式更快。(t是要展平的列表。)

下面是对应的函数:

def flatten(t):
    return [item for sublist in t for item in sublist]

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

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

说明:基于+(包括 in 的隐含使用sum)的快捷方式是,O(T**2)当有 T 个子列表时——随着中间结果列表越来越长,每一步都会分配一个新的中间结果列表对象,并且所有项目必须复制之前的中间结果(以及最后添加的一些新结果)。因此,为简单起见且不失一般性,假设每个子列表都有 k 个项目:前 k 个项目来回复制 T-1 次,后 k 个项目 T-2 次,依此类推;对于从 1 到 T 排除的 x,副本总数是 x 总和的 k 倍,即k * (T**2)/2

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

2022-01-09