欢迎访问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循环也挺好的。

声明:本网站资源来源于网络收集,如有侵权,请联系站长进行删除处理。 分享目的仅供大家学习和交流,请不要用于商业用途,否则后果自负。本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解。本站资源售价只是赞助,收取费用仅维持本站的日常运营所需。反馈邮箱:1159995880@qq.com