欢迎访问Python每天3分钟系列。
每天早上8点半,花3分钟时间,学习或温习一个Python知识点。
今天是第003篇:如何高效的把二维列表合并成一维?也就是打平
要实现的目标
有如下列表:
nums_2d = [[12,3],[4,5,6,7],[8,9]]
要求把它合并成一维列表:
nums_1d = [1,2,3,4,5,6,7,8,9]
普通青年的方法
普通青年使用for循环和extend函数:
nums_2d = [[1,2,3],[4,5,6,7],[8,9]]
nums_1d = []
for n in nums_2d:
nums_1d.extend(n)
print(nums_1d)
extend() 函数把一个列表里的元素逐个添加到前面的列表中。这里不能使用 +,因为这样会把子列表作为一个元素加进去,没有实现打平的目的。
如果要一定使用+也可以,那要使用两层的for循环,效率比较差。
文艺青年的方法
上面的实现竟然用了3行代码,这样一点都不pythonic,来个文艺点的做法,一行搞定:
nums_2d = [[1,2,3],[4,5,6,7],[8,9]]
nums_1d = [item for sublist in nums_2d for item in sublist]
print(nums_1d)
这里用了推导式,里面稍微有点难以理解。你可以这样想:
-
这就是个两层for循环,前面是外层循环(加粗),后面内层循环:item for sublist in nums_2d for item in sublist -
内层循环的结果(也就是item变量)都放在一个列表中,这样就实现了打平的效果
博士青年的方法
如果你见多识广,可能会用functools的reduce方法:
import functools, operator
nums_2d = [[1,2,3],[4,5,6,7],[8,9]]
nums_1d = functools.reduce(operator.concat, nums_2d)
print(nums_1d)
functools的reduce函数会把nums_2d中的子列表逐次合并(operator.concat),直到里面只有一个列表为止,从而也实现了打平的目的。
这里除了用operator.concat,也可以自己传入一个函数,或者就地定义一个匿名函数:
import functools
nums_2d = [[1,2,3],[4,5,6,7],[8,9]]
nums_1d = functools.reduce(lambda x, y: x + y, nums_2d)
print(nums_1d)
还有其他更多的方法,但是没必要像孔乙己数茴香豆一样:列举茴香豆的茴字有8种写法。
那个最快
那个效率更好一点呢?
数据说话,用timeit来测试一下他们的效率:
-
普通青年 – 12.5 maishu@msmacbook ~ % python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'n=[]' 'for tt in t:' ' n.extend(tt)' 20000 loops, best of 5: 12.4 usec per loop
-
普通青年 – 16.5 maishu@msmacbook ~ % python -mtimeit -s'nums_2d=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in nums_2d for item in sublist]' 20000 loops, best of 5: 16.5 usec per loop
-
博士青年 – 219,238 maishu@msmacbook ~ % python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'import functools' 'import operator' 'functools.reduce(operator.concat,t)' 1000 loops, best of 5: 219 usec per loop
maishu@msmacbook ~ % python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'import functools' 'functools.reduce(lambda x,y: x+y,t)' 1000 loops, best of 5: 238 usec per loop
普通青年完胜!看来做个普通青年也没什么不好的。不是吗?
有时候我们会为了pythonic而pythonic,总想一行代码实现一个功能,到处找最好的方法,其实写个简单的for循环也挺好的。
原文链接:https://www.afxvip.com/4888.html,转载请注明出处。
评论0