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中Django框架下的staticfiles使用简介
May 30 Python
python利用OpenCV2实现人脸检测
Apr 16 Python
Python使用numpy实现BP神经网络
Mar 10 Python
python2 与 pyhton3的输入语句写法小结
Sep 10 Python
Python实现账号密码输错三次即锁定功能简单示例
Mar 29 Python
Python 中Django安装和使用教程详解
Jul 03 Python
解决Django中调用keras的模型出现的问题
Aug 07 Python
手把手教你进行Python虚拟环境配置教程
Feb 03 Python
python 异步async库的使用说明
May 04 Python
keras实现基于孪生网络的图片相似度计算方式
Jun 11 Python
解决Jupyter-notebook不弹出默认浏览器的问题
Mar 30 Python
Matlab如何实现矩阵复制扩充
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
用DBSQL类加快开发MySQL数据库程序的速度
2006/10/09 PHP
php判断字符以及字符串的包含方法属性
2008/08/30 PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
2014/07/28 PHP
PHP中使用register_shutdown_function函数截获fatal error示例
2015/04/21 PHP
PHP实现将textarea的值根据回车换行拆分至数组
2015/06/10 PHP
CodeIgniter框架验证码类库文件与用法示例
2017/03/18 PHP
PHP 无限级分类
2017/05/04 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
PHP使用PDO抽象层获取查询结果的方法示例
2018/05/10 PHP
js onload事件不起作用示例分析
2013/10/09 Javascript
js实现在字符串中提取数字
2013/11/05 Javascript
JavaScript通过select动态更换图片的方法
2015/03/23 Javascript
网页挂马方式整理及详细介绍
2016/11/03 Javascript
实例解析jQuery中如何取消后续执行内容
2016/12/01 Javascript
Angularjs中的ui-bootstrap的使用教程
2017/02/19 Javascript
vue 文件目录结构详解
2017/11/24 Javascript
如何在微信小程序里面退出小程序的方法
2019/04/28 Javascript
在vue中使用vuex,修改state的值示例
2019/11/08 Javascript
基于脚手架创建Vue项目实现步骤详解
2020/08/03 Javascript
原生JavaScript实现随机点名表
2021/01/14 Javascript
js实现电灯开关效果
2021/01/19 Javascript
Python创建普通菜单示例【基于win32ui模块】
2018/05/09 Python
Python3网络爬虫中的requests高级用法详解
2019/06/18 Python
详解pandas使用drop_duplicates去除DataFrame重复项参数
2019/08/01 Python
python return逻辑判断表达式实现解析
2019/12/02 Python
python由已知数组快速生成新数组的方法
2020/04/08 Python
世界上最好的旅行夹克:BauBax
2018/12/23 全球购物
采购部部门职责
2013/12/15 职场文书
秦兵马俑教学反思
2014/02/07 职场文书
出纳试用期自我鉴定
2014/04/07 职场文书
家长写给孩子的评语
2014/04/18 职场文书
2015年党风廉政建设个人总结
2015/08/18 职场文书
python 如何在list中找Topk的数值和索引
2021/05/20 Python
Python数据分析之绘图和可视化详解
2021/06/02 Python
MySQL 那些常见的错误设计规范,你都知道吗
2021/07/16 MySQL
浅谈Redis变慢的原因及排查方法
2022/06/21 Redis