Python 把两层列表展开平铺成一层(5种实现方式)


Posted in Python onApril 07, 2021

这几天和同事在讨论,如何用 Python 写出优雅的让列表中的列表展开,变成扁平化的列表。

例如

# 期望输入
input = [[('A', 1), ('B', 2)], [('C', 3), ('D', 4)]]
 
# 期望输出
output = [('A', 1), ('B', 2), ('C', 3), ('D', 4)]

map 函数合并

>>> new = []; map(new.extend, input); new
[None, None]
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

这个方法看上去还可以,但是有个致命的缺点,就是map函数会返回值,并且这个返回值是没有用的。另外还需要提前声明一个变量,从代码的简洁性上,不够简洁优雅。

sum 函数合并

>>> sum(input, [])
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

这个看上去很简洁,不过有类似字符串累加的性能陷阱。后面有性能对比。

reduce 函数

>>> reduce(list.__add__, input)
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

做序列的累加操作。也是有累加的性能陷阱。

列表推导式

>>> [item for sublist in input for item in sublist]
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

列表推导式,看着有些长,而且还要for循环两次,变成一行理解需要费劲一些,没有那么直观。

itertools 类库

>>> list(itertools.chain(*input))
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

通过第三方类库类实现的,相比其他的几个实现,看着还算比较优雅。最后的性能发现居然还很高。

性能大对比

python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(list.__add__,l)'
1000 loops, best of 3: 547 usec per loop
python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 509 usec per loop
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: 52.8 usec per loop
python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99; import itertools;' 'list(itertools.chain(*l))'
10000 loops, best of 3: 35.9 usec per loop
python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'new = []; map(new.extend, l); new'
10000 loops, best of 3: 34.1 usec per loop

欢迎大家共同探讨优雅的的实现和性能的优化。

补充:python 将(含嵌套的)dict平铺展开

话不多说,直接上代码:

def prefix_dict(di_, prefix_s=''):
  """
  把字典的每个key都带上前缀prefix_s
  :param di_:
  :param prefix_s:
  :return:
  """
  return {prefix_s + k: v for k, v in di_.items()} 
 
def spear_dict(di_, con_s='.'):
  """
  展开dict(如果下层还是dict),需要递归,展开到下层的数据类型不是字典为止
  可能实用的地方:将文档类的数据格式化成更加关系化的样子可能有用
  :param di_: 输入字典
  :param con_s: 层级间的连接符号
  :return: 深度不大于1的字典,嵌套的其他数据类型照旧
  """
  ret_di = {}
  for k, v in di_.items():
    if type(v) is dict:
      v = spear_dict(v)
      # 这里或许有不写到这一层的更好写法
      # for k_, v_ in v.items():
      #   ret_di.update({con_s.join([k, k_]): v_})
      ret_di.update(prefix_dict(v, prefix_s=k + con_s))
    else:
      ret_di.update({k: v})
  return ret_di
>>> di_
{'title': '新田商业街', 'reliability': 7, 'addressComponents': {'streetNumber': '', 'city': '深圳市', 'street': '', 'province': '广东省', 'district': '龙华区'}, 'location': {'lng': 114.09127044677734, 'lat': 22.700519561767578}, 'adInfo': {'adcode': '440309'}, 'level': 11, 'more_deep': {'loca': {'lng': 114.09127044677734, 'lat': 22.700519561767578}}}
>>> spear_dict(di_)
{'title': '新田商业街', 'reliability': 7, 'addressComponents.streetNumber': '', 'addressComponents.city': '深圳市', 'addressComponents.street': '', 'addressComponents.province': '广东省', 'addressComponents.district': '龙华区', 'location.lng': 114.09127044677734, 'location.lat': 22.700519561767578, 'adInfo.adcode': '440309', 'level': 11, 'more_deep.loca.lng': 114.09127044677734, 'more_deep.loca.lat': 22.700519561767578}
spear_dict(di_, '_')
{'title': '新田商业街', 'reliability': 7, 'addressComponents_streetNumber': '', 'addressComponents_city': '深圳市', 'addressComponents_street': '', 'addressComponents_province': '广东省', 'addressComponents_district': '龙华区', 'location_lng': 114.09127044677734, 'location_lat': 22.700519561767578, 'adInfo_adcode': '440309', 'level': 11, 'more_deep_loca.lng': 114.09127044677734, 'more_deep_loca.lat': 22.700519561767578}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Python 相关文章推荐
让python的Cookie.py模块支持冒号做key的方法
Dec 28 Python
Python下线程之间的共享和释放示例
May 04 Python
解决uWSGI的编码问题详解
Mar 24 Python
python实现TF-IDF算法解析
Jan 02 Python
python OpenCV学习笔记之绘制直方图的方法
Feb 08 Python
python opencv实现切变换 不裁减图片
Jul 26 Python
从DataFrame中提取出Series或DataFrame对象的方法
Nov 10 Python
深入浅析Python2.x和3.x版本的主要区别
Nov 30 Python
浅谈python3.x pool.map()方法的实质
Jan 16 Python
Python Pillow.Image 图像保存和参数选择方式
Jan 09 Python
Django-xadmin+rule对象级权限的实现方式
Mar 30 Python
利用PyTorch实现VGG16教程
Jun 24 Python
Python获取百度热搜的完整代码
详解Python小数据池和代码块缓存机制
Apr 07 #Python
浅谈Python列表嵌套字典转化的问题
Apr 07 #Python
python pyhs2 的安装操作
Apr 07 #Python
python3 sqlite3限制条件查询的操作
Apr 07 #Python
python实现高效的遗传算法
解决hive中导入text文件遇到的坑
Apr 07 #Python
You might like
PhpSpreadsheet设置单元格常用操作汇总
2020/11/13 PHP
js对象的构造和继承实现代码
2010/12/05 Javascript
菜鸟javascript基础整理1
2010/12/06 Javascript
jquery动画4.升级版遮罩效果的图片走廊--带自动运行效果
2012/08/24 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(三)情景对话中仿打字机输出文字
2013/01/23 Javascript
正负小数点后两位浮点数实现原理及代码
2013/09/06 Javascript
js showModalDialog弹出窗口实例详解
2014/01/07 Javascript
JavaScript常用小技巧小结
2014/12/29 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
快速掌握Node.js之Window下配置NodeJs环境
2016/03/21 NodeJs
Bootstrap插件全集
2016/07/18 Javascript
Vue.js学习笔记之 helloworld
2016/08/14 Javascript
微信小程序 详解Page中data数据操作和函数调用
2017/01/12 Javascript
JS实现中国公民身份证号码有效性验证
2017/02/20 Javascript
jQuery实现火车票买票城市选择切换功能
2017/09/15 jQuery
JS兼容所有浏览器的DOMContentLoaded事件
2018/01/12 Javascript
解决微信授权成功后点击按返回键出现空白页和报错的问题
2020/06/08 Javascript
微信小程序反编译的实现
2020/12/10 Javascript
Python随手笔记之标准类型内建函数
2015/12/02 Python
python中正则的使用指南
2016/12/04 Python
python批量赋值操作实例
2018/10/22 Python
对pytorch网络层结构的数组化详解
2018/12/08 Python
PyQtGraph在pyqt中的应用及安装过程
2019/08/04 Python
django-filter和普通查询的例子
2019/08/12 Python
python matplotlib实现将图例放在图外
2020/04/17 Python
如何基于python实现不邻接植花
2020/05/01 Python
pytorch 把图片数据转化成tensor的操作
2021/03/04 Python
HTML5新增加的功能详解
2016/09/05 HTML / CSS
Sofmap官网:日本著名的数码电器专卖店
2017/05/19 全球购物
会展中心部门工作职责
2013/11/27 职场文书
小学美术兴趣小组活动总结
2014/07/07 职场文书
公司租房协议书
2014/10/14 职场文书
搞笑婚前保证书
2015/02/28 职场文书
企业办公室主任岗位职责
2015/04/01 职场文书
2015年加油站站长工作总结
2015/05/27 职场文书
趣味运动会口号
2015/12/24 职场文书