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 相关文章推荐
天翼开放平台免费短信验证码接口使用实例
Dec 18 Python
简单的连接MySQL与Python的Bottle框架的方法
Apr 30 Python
Python中类型关系和继承关系实例详解
May 25 Python
Python爬虫之xlml解析库(全面了解)
Aug 08 Python
Python探索之创建二叉树
Oct 25 Python
Django开发中复选框用法示例
Mar 20 Python
使用Django2快速开发Web项目的详细步骤
Jan 06 Python
Python3使用TCP编写一个简易的文件下载器功能
May 08 Python
python移位运算的实现
Jul 15 Python
在tensorflow中实现去除不足一个batch的数据
Jan 20 Python
python中的被动信息搜集
Apr 29 Python
Python制作表白爱心合集
Jan 22 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+MYSQL开发工具及资源收藏
2007/01/02 PHP
如何使用Strace调试工具
2013/06/03 PHP
如何修改和添加Apache的默认站点目录
2013/07/05 PHP
ThinkPHP模板判断输出Defined标签用法详解
2014/06/30 PHP
CI框架封装的常用图像处理方法(缩略图,水印,旋转,上传等)
2016/11/22 PHP
Javascript 日期处理之时区问题
2009/10/08 Javascript
JavaScript中的null和undefined解析
2012/04/14 Javascript
js调试系列 控制台命令行API使用方法
2014/06/18 Javascript
jQuery事件用法实例汇总
2014/08/29 Javascript
JS+CSS实现下拉列表框美化效果(3款)
2015/08/15 Javascript
莱鸟介绍javascript onclick事件
2016/01/06 Javascript
Vue.js 表单校验插件
2016/08/14 Javascript
js如何判断是否在iframe中及防止网页被别站用iframe嵌套
2017/01/11 Javascript
Vuejs2 + Webpack框架里,模拟下载的实例讲解
2018/09/05 Javascript
[01:57]DOTA2上海特锦赛小组赛解说单车采访花絮
2016/02/27 DOTA
Python的Django REST框架中的序列化及请求和返回
2016/04/11 Python
Python中logging实例讲解
2019/01/17 Python
Python计算时间间隔(精确到微妙)的代码实例
2019/02/26 Python
详解Python3之数据指纹MD5校验与对比
2019/06/11 Python
django框架面向对象ORM模型继承用法实例分析
2019/07/29 Python
分享一个pycharm专业版安装的永久使用方法
2019/09/24 Python
PyCharm 2019.3发布增加了新功能一览
2019/12/08 Python
pytorch GAN生成对抗网络实例
2020/01/10 Python
用Python爬取LOL所有的英雄信息以及英雄皮肤的示例代码
2020/07/13 Python
linux centos 7.x 安装 python3.x 替换 python2.x的过程解析
2020/12/14 Python
用pip给python安装matplotlib库的详细教程
2021/02/24 Python
澳洲国民品牌乡村路折扣店:Country Road & Trenery Outlet
2018/04/19 全球购物
台湾时尚彩瞳专门店:imeime
2019/08/16 全球购物
小学教师师德反思
2014/02/03 职场文书
企业道德讲堂实施方案
2014/03/19 职场文书
2014年安全生产目标责任书
2014/07/23 职场文书
环保志愿者活动方案
2014/08/14 职场文书
2014年教学工作总结
2014/11/13 职场文书
CAD实训总结范文
2015/08/03 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python
python实现会员管理系统
2022/03/18 Python