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回溯法实现数组全排列输出实例分析
Mar 17 Python
python实现可以断点续传和并发的ftp程序
Sep 13 Python
python中requests爬去网页内容出现乱码问题解决方法介绍
Oct 25 Python
python实现内存监控系统
Mar 07 Python
在IPython中执行Python程序文件的示例
Nov 01 Python
python 自定义装饰器实例详解
Jul 20 Python
关于tensorflow的几种参数初始化方法小结
Jan 04 Python
Python pip安装模块提示错误解决方案
May 22 Python
django rest framework 过滤时间操作
Jul 12 Python
基于python tkinter的点名小程序功能的实例代码
Aug 22 Python
python 绘制国旗的示例
Sep 27 Python
python 实现两个变量值进行交换的n种操作
Jun 02 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
PHP网站建设的流程与步骤分享
2015/09/25 PHP
关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析
2016/01/08 PHP
PHP+Ajax实现验证码的实时验证
2016/07/20 PHP
对YUI扩展的Gird组件 Part-2
2007/03/10 Javascript
jQuery powerFloat万能浮动层下拉层插件使用介绍
2010/12/27 Javascript
使用JSLint提高JS代码质量方法分享
2013/12/16 Javascript
javascript计时器事件使用详解
2014/01/07 Javascript
用jquery的方法制作一个简单的导航栏
2014/06/23 Javascript
NodeJS学习笔记之(Url,QueryString,Path)模块
2015/01/13 NodeJs
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
node.js下LDAP查询实例分享
2015/09/30 Javascript
有关json_decode乱码及NULL的问题
2015/10/13 Javascript
基于jQuery的ajax方法封装
2016/07/14 Javascript
jQuery插件zTree实现的多选树效果示例
2017/03/08 Javascript
vue实现长图垂直居上 vue实现短图垂直居中
2017/10/18 Javascript
node.js中对Event Loop事件循环的理解与应用实例分析
2020/02/14 Javascript
Node.js API详解之 Error模块用法实例分析
2020/05/14 Javascript
React+EggJs实现断点续传的示例代码
2020/07/07 Javascript
vue监听dom大小改变案例
2020/07/29 Javascript
Openlayers绘制地图标注
2020/09/28 Javascript
JS canvas实现画板和签字板功能
2021/02/23 Javascript
python批量添加zabbix Screens的两个脚本分享
2017/01/16 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
基于h5py的使用及数据封装代码
2019/12/26 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
2020/01/02 Python
零基础小白多久能学会python
2020/06/22 Python
在pycharm创建scrapy项目的实现步骤
2020/12/01 Python
乔丹诺(Giordano)酒庄德国官网:找到最好的意大利葡萄酒
2017/12/28 全球购物
行政部主管岗位职责
2013/12/28 职场文书
校优秀毕业生主要事迹
2014/05/26 职场文书
八荣八耻演讲稿
2014/09/15 职场文书
放假通知怎么写
2015/08/18 职场文书
2019思想汇报范文
2019/05/21 职场文书
python 模拟在天空中放风筝的示例代码
2021/04/21 Python
Java基于Dijkstra算法实现校园导游程序
2022/03/17 Java/Android
动画「进击的巨人」第86话播出感谢绘公开
2022/03/21 日漫