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写的一个简单DNS服务器实例
Jun 04 Python
Djang中静态文件配置方法
Jul 30 Python
python爬取指定微信公众号文章
Dec 20 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
May 10 Python
django中使用Celery 布式任务队列过程详解
Jul 29 Python
通过selenium抓取某东的TT购买记录并分析趋势过程解析
Aug 15 Python
Python计算不规则图形面积算法实现解析
Nov 22 Python
在OpenCV里实现条码区域识别的方法示例
Dec 04 Python
python基于plotly实现画饼状图代码实例
Dec 16 Python
关于Python中定制类的比较运算实例
Dec 19 Python
如何使用python写截屏小工具
Sep 29 Python
python不同版本的_new_不同点总结
Dec 09 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伪静态的实现详细介绍
2013/04/28 PHP
php中的curl使用入门教程和常见用法实例
2014/04/10 PHP
浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
2015/10/26 PHP
PHP中类属性与类静态变量的访问方法示例
2016/07/13 PHP
Laravel 5.3 学习笔记之 配置
2016/08/28 PHP
php curl发送请求实例方法
2019/08/01 PHP
javascript 模式设计之工厂模式学习心得
2010/04/27 Javascript
javascript与jquery中跳出循环的区别总结
2013/11/04 Javascript
JavaScript中使用typeof运算符需要注意的几个坑
2014/11/08 Javascript
JavaScript开发人员的10个关键习惯小结
2014/12/05 Javascript
DOM基础教程之事件对象
2015/01/20 Javascript
IE下支持文本框和密码框placeholder效果的JQuery插件分享
2015/01/31 Javascript
JavaScript 变量、作用域及内存
2015/04/08 Javascript
jquery关于事件冒泡和事件委托的技巧及阻止与允许事件冒泡的三种实现方法
2015/11/27 Javascript
JavaScript 数组some()和filter()的用法及区别
2016/05/20 Javascript
JavaScript中判断数据类型的方法总结
2016/05/24 Javascript
Js+Ajax,Get和Post在使用上的区别小结
2016/06/08 Javascript
Vue的生命周期操作示例
2019/09/17 Javascript
一文秒懂JavaScript构造函数、实例、原型对象以及原型链
2020/08/25 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
2020/09/22 Javascript
在Python中调用ggplot的三种方法
2015/04/08 Python
python中的错误处理
2016/04/10 Python
python 实现从高分辨图像上抠取图像块
2020/01/02 Python
美国办公用品购物网站:Quill.com
2016/09/01 全球购物
Office DEPOT法国官网:欧迪办公用品采购
2018/01/03 全球购物
linux面试题参考答案(7)
2012/10/29 面试题
四年级科学教学反思
2014/02/10 职场文书
创建省级文明单位实施方案
2014/02/27 职场文书
党员群众路线教育实践活动学习笔记
2014/11/05 职场文书
素质教育学习心得体会
2016/01/19 职场文书
python3.9之你应该知道的新特性详解
2021/04/29 Python
新手入门Mysql--sql执行过程
2021/06/20 MySQL
Jedis操作Redis实现模拟验证码发送功能
2021/09/25 Redis
Windows下用Nginx配置https服务器及反向代理的问题
2021/09/25 Servers
简单聊聊Vue中的计算属性和属性侦听
2021/10/05 Vue.js
VMware虚拟机安装 Windows Server 2022的详细图文教程
2022/09/23 Servers