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定时采集摄像头图像上传ftp服务器功能实现
Dec 23 Python
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 Python
Python中使用Flask、MongoDB搭建简易图片服务器
Feb 04 Python
如何准确判断请求是搜索引擎爬虫(蜘蛛)发出的请求
Oct 13 Python
python smtplib模块自动收发邮件功能(一)
May 22 Python
Django+Ajax+jQuery实现网页动态更新的实例
May 28 Python
windows下搭建python scrapy爬虫框架步骤
Dec 23 Python
Python在cmd上打印彩色文字实现过程详解
Aug 07 Python
python实现证件照换底功能
Aug 20 Python
python编写计算器功能
Oct 25 Python
django rest framework 过滤时间操作
Jul 12 Python
Python中glob库实现文件名的匹配
Jun 18 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调用C代码的实现方法
2014/03/11 PHP
PHP中使用foreach()遍历二维数组的简单实例
2016/06/13 PHP
tp5(thinkPHP5)操作mongoDB数据库的方法
2018/01/20 PHP
PHP中检查isset()和!empty()函数的必要性
2019/02/13 PHP
!DOCTYPE声明对JavaScript的影响分析
2010/04/12 Javascript
JQuery EasyUI 对话框的使用方法
2010/10/24 Javascript
javascript页面加载完执行事件代码
2014/02/11 Javascript
原生javascript实现的分页插件pagenav
2014/08/28 Javascript
Js可拖拽放大的层拖动特效实现方法
2015/02/25 Javascript
js实时获取并显示当前时间的方法
2015/07/31 Javascript
基于jquery实现页面滚动时顶部导航显示隐藏
2020/04/20 Javascript
javascript实现右侧弹出“分享到”窗口效果
2016/02/01 Javascript
JS制作图形验证码实现代码
2020/10/19 Javascript
Angular4学习教程之DOM属性绑定详解
2018/01/04 Javascript
react实现点击选中的li高亮的示例代码
2018/05/24 Javascript
详解Vuex下Store的模块化拆分实践
2019/07/31 Javascript
微信小程序动画组件使用解析,类似vue,且更强大
2019/08/01 Javascript
vue中父子组件传值,解决钩子函数mounted只运行一次的操作
2020/07/27 Javascript
Python字典简介以及用法详解
2016/11/15 Python
python 搭建简单的http server,可直接post文件的实例
2019/01/03 Python
Python 常用模块 re 使用方法详解
2019/06/06 Python
python实现梯度下降法
2020/03/24 Python
解决TensorFlow调用Keras库函数存在的问题
2020/07/06 Python
python 使用三引号时容易犯的小错误
2020/10/21 Python
WoolOvers爱尔兰:羊绒、羊毛和棉针织品
2017/01/04 全球购物
澳大利亚领先的在线美容商店:Facial Co
2017/10/22 全球购物
expedia比利时:预订航班+酒店并省钱
2018/07/13 全球购物
德国运动营养和健身网上商店:Myprotein.de
2018/07/18 全球购物
聚美优品的广告词
2014/03/14 职场文书
经贸日语专业个人求职信范文
2014/04/29 职场文书
消防安全承诺书
2014/05/22 职场文书
计算机应用专业毕业生求职信
2014/06/03 职场文书
机关干部四风问题自我剖析及整改措施
2014/10/26 职场文书
2014年健康教育工作总结
2014/11/20 职场文书
房产公证书格式
2015/01/26 职场文书
干部考核工作总结2015
2015/07/24 职场文书