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

新手上路,请多包涵

我有一个列表列表,例如 [[1, 2, 3], [4, 5, 6], [7], [8, 9]] 。如何将其展平以获得 [1, 2, 3, 4, 5, 6, 7, 8, 9]


如果您的列表列表来自嵌套列表推导,则可以通过修复推导更简单/直接地解决问题;请参阅 python 列表推导;压缩列表列表? .

这里最流行的解决方案通常只展平嵌套列表的一个“级别”。请参阅展 平不规则(任意嵌套)列表列表 以获得完全展平深度嵌套结构(通常是递归)的解决方案。

原文由 Emma 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 460
2 个回答

给定一个列表列表 l

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

意思是:

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

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

下面是对应的函数:

 def flatten(l):
    return [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 中的隐含使用)的快捷方式,必然是 O(L**2) 当有L子列表时—作为中间结果列表越来越长,每一步都会分配一个新的中间结果列表对象,并且必须复制上一个中间结果中的所有项目(以及最后添加的一些新项目)。因此,为简单起见且不失一般性,假设您有 L 个包含 I 项的子列表:第一个 I 项被来回复制 L-1 次,第二个 I 项被复制 L-2 次,依此类推;副本总数是从 1 到 L 排除的 x 的总和的 I 倍,即 I * (L**2)/2

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

原文由 Alex Martelli 发布,翻译遵循 CC BY-SA 4.0 许可协议

您可以使用 itertools.chain()

 >>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

或者您可以使用 itertools.chain.from_iterable() 不需要使用 * 运算符解压列表:

 >>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

这种方法可以说比 [item for sublist in l for item in sublist] 更具可读性,而且似乎也更快:

 $ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
20000 loops, best of 5: 10.8 usec per loop
$ python3 -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 5: 21.7 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 5: 258 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;from functools import reduce' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 5: 292 usec per loop
$ python3 --version
Python 3.7.5rc1

原文由 Shawn Chin 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题