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中将阿拉伯数字转换成中文的实现代码
May 19 Python
Python编写的com组件发生R6034错误的原因与解决办法
Apr 01 Python
Django中URL视图函数的一些高级概念介绍
Jul 20 Python
Django在win10下的安装并创建工程
Nov 20 Python
使用python实现链表操作
Jan 26 Python
使用python的pexpect模块,实现远程免密登录的示例
Feb 14 Python
Python3最长回文子串算法示例
Mar 04 Python
numpy concatenate数组拼接方法示例介绍
May 27 Python
tensorflow对图像进行拼接的例子
Feb 05 Python
Jmeter HTTPS接口测试证书导入过程图解
Jul 22 Python
python获取命令行参数实例方法讲解
Nov 02 Python
python re模块常见用法例举
Mar 01 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
当年上海收录机产品生产,进口和价格情况
2021/03/04 无线电
php二分法在IP地址查询中的应用
2008/08/12 PHP
fleaphp crud操作之find函数的使用方法
2011/04/23 PHP
php数据类型判断函数有哪些
2013/09/23 PHP
PHP获取中英混合字符串长度的方法
2014/06/07 PHP
YiiFramework入门知识点总结(图文教程)
2015/12/28 PHP
实例详解PHP中html word 互转的方法
2016/01/28 PHP
php集成开发环境详解
2019/09/24 PHP
Laravel实现通过blade模板引擎渲染视图
2019/10/25 PHP
Javascript堆排序算法详解
2014/12/03 Javascript
js仿微博实现统计字符和本地存储功能
2015/12/22 Javascript
理解js回收机制通俗易懂版
2016/02/29 Javascript
JavaScript的ExtJS框架中数面板TreePanel的使用实例解析
2016/05/21 Javascript
详解vue前后台数据交互vue-resource文档
2017/07/19 Javascript
JS实现获取汉字首字母拼音、全拼音及混拼音的方法
2017/11/14 Javascript
vue init失败简单解决方法(终极版)
2017/12/22 Javascript
JS面向对象的程序设计相关知识小结
2018/05/26 Javascript
如何为你的JavaScript代码日志着色详解
2019/04/08 Javascript
Python中threading模块join函数用法实例分析
2015/06/04 Python
Python内置函数reversed()用法分析
2018/03/20 Python
Django项目中用JS实现加载子页面并传值的方法
2018/05/28 Python
Numpy截取指定范围内的数据方法
2018/11/14 Python
Python和Java的语法对比分析语法简洁上python的确完美胜出
2019/05/10 Python
获取django框架orm query执行的sql语句实现方法分析
2019/06/20 Python
django框架防止XSS注入的方法分析
2019/06/21 Python
python logging模块的使用总结
2019/07/09 Python
python dataframe NaN处理方式
2019/12/26 Python
python sleep和wait对比总结
2021/02/03 Python
html5简单示例_动力节点Java学院整理
2017/07/07 HTML / CSS
墨尔本照明批发商店:Mica Lighting
2017/12/28 全球购物
C和C++经典笔试题附答案解析
2014/08/18 面试题
金山毒霸系列的笔试题
2013/04/13 面试题
平面设计的岗位职责
2013/11/08 职场文书
大学生活自我评价
2014/04/09 职场文书
公司市场专员岗位职责
2014/06/29 职场文书
股东授权委托书范本
2014/09/13 职场文书