Python中多层List展平为一层

使用Python脚本的过程中,偶尔需要使用list多层转一层,又总是忘记怎么写搜索关键词,所以总是找了很久,现在把各种方法记录下来,方便自己也方便大家.

方法很多,现在就简单写8种,后面再对这8种方法做基准测试.

声明:文中的方法均收集自Making a flat list out of list of lists in Python

方法汇总

1.定义减层方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import functools
import itertools
import numpy
import operator
import perfplot
from collections import Iterable # or from collections.abc import Iterable
from iteration_utilities import deepflatten

#使用两次for循环
def forfor(a):
return [item for sublist in a for item in sublist]

#通过sum
def sum_brackets(a):
return sum(a, [])

#使用functools內建模块
def functools_reduce(a):
return functools.reduce(operator.concat, a)

#使用itertools內建模块
def itertools_chain(a):
return list(itertools.chain.from_iterable(a))

#使用numpy
def numpy_flat(a):
return list(numpy.array(a).flat)

#使用numpy
def numpy_concatenate(a):
return list(numpy.concatenate(a))

#自定义函数
def flatten(items):
"""Yield items from any nested iterable; see REF."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
yield from flatten(x)
else:
yield x

def pylangs_flatten(a):
return list(flatten(a))

#使用库iteration_utilities
def iteration_utilities_deepflatten(a):
return list(deepflatten(a, depth=1))

2.测试

1
2
3
4
5
6
7
8
9
10
11
12
13
a=[[1,2,3],[4,5,6],[7,8,9]]
print(a)

print('--------------------------')

print(forfor(a))
print(sum_brackets(a))
print(functools_reduce(a))
print(itertools_chain(a))
print(numpy_flat(a))
print(numpy_concatenate(a))
print(pylangs_flatten(a))
print(iteration_utilities_deepflatten(a))

输出:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
--------------------------
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]


各种方法的基准测试(消耗时间对比)

各种方法在小数据上消耗时间差别不大,如果数据很小,没必要为了选择而烦恼,如果数据很大,可以参考下面基准测试的结果来选择减层方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import matplotlib.pyplot as plt
from simple_benchmark import benchmark

#基准测试
b = benchmark(
[forfor, sum_brackets, functools_reduce, itertools_chain,numpy_flat, numpy_concatenate, pylangs_flatten,iteration_utilities_deepflatten],
arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
argument_name='number of inner lists'
)

#显示测试结果
plt.subplots(1,1,figsize=(15,10))
b.plot()
plt.legend(loc = 'upper left')
plt.show()

消耗时间对比

相同数据量,纵轴方向越小,方法越快.


代码可以从这里下载,需要部署Jupyter环境,可参考我的博客部署方法.