Python中如何优雅的合并两个字典(dict)方法示例


Posted in Python onAugust 09, 2017

前言

字典是Python中最强大的数据类型之一,本文将给大家详细介绍关于Python合并两个字典(dict)的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍吧。

一行代码合并两个dict

假设有两个dict x和y,合并成一个新的dict,不改变 x和y的值,例如

x = {'a': 1, 'b': 2}
 y = {'b': 3, 'c': 4}

期望得到一个新的结果Z,如果key相同,则y覆盖x。期望的结果是

>>> z
{'a': 1, 'b': 3, 'c': 4}

在PEP448中,有个新的语法可以实现,并且在python3.5中支持了该语法,合并代码如下

z = {**x, **y}

妥妥的一行代码。 由于现在很多人还在用python2,对于python2和python3.0-python3.4的人来说,有一个比较优雅的方法,但是需要两行代码。

z = x.copy()
z.update(y)

上面的方法,y都会覆盖x里的内容,所以最终结果b=3.

不使用python3.5如何一行完成了

如果您还没有使用Python 3.5,或者需要编写向后兼容的代码,并且您希望在单个表达式中运行,则最有效的方法是将其放在一个函数中:

def merge_two_dicts(x, y):
 """Given two dicts, merge them into a new dict as a shallow copy."""
 z = x.copy()
 z.update(y)
 return z

然后一行代码完成调用:

z = merge_two_dicts(x, y)

你也可以定义一个函数,合并多个dict,例如

def merge_dicts(*dict_args):
 """
 Given any number of dicts, shallow copy and merge into a new dict,
 precedence goes to key value pairs in latter dicts.
 """
 result = {}
 for dictionary in dict_args:
 result.update(dictionary)
 return result

然后可以这样使用

z = merge_dicts(a, b, c, d, e, f, g)

所有这些里面,相同的key,都是后面的覆盖前面的。

一些不够优雅的示范

items

有些人会使用这种方法:

z = dict(x.items() + y.items())

这其实就是在内存中创建两个列表,再创建第三个列表,拷贝完成后,创建新的dict,删除掉前三个列表。这个方法耗费性能,而且对于python3,这个无法成功执行,因为items()返回是个对象。

>>> c = dict(a.items() + b.items())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict_items' and 
'dict_items'

你必须明确的把它强制转换成list,z = dict(list(x.items()) + list(y.items())) ,这太浪费性能了。 另外,想以来于items()返回的list做并集的方法对于python3来说也会失败,而且,并集的方法,导致了重复的key在取值时的不确定,所以,如果你对两个dict合并有优先级的要求,这个方法就彻底不合适了。

>>> x = {'a': []}
>>> y = {'b': []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

这里有一个例子,其中y应该具有优先权,但是由于任意的集合顺序,x的值被保留:

>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}

构造函数

也有人会这么用

z = dict(x, **y)

这样用很好,比前面的两步的方法高效多了,但是可阅读性差,不够pythonic,如果当key不是字符串的时候,python3中还是运行失败

>>> c = dict(a, **b)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

Guido van Rossum 大神说了:宣告dict({}, {1:3})是非法的,因为毕竟是滥用机制。虽然这个方法比较hacker,但是太投机取巧了。

一些性能较差但是比较优雅的方法

下面这些方法,虽然性能差,但也比items方法好多了。并且支持优先级。

{k: v for d in dicts for k, v in d.items()}

python2.6中可以这样

dict((k, v) for d in dicts for k, v in d.items())

itertools.chain 将以正确的顺序将键值对上的迭代器链接:

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

性能测试

以下是在Ubuntu 14.04上完成的,在Python 2.7(系统Python)中:

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.5726828575134277
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.163769006729126
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(),y.iteritems()))))
1.1614501476287842
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
2.2345519065856934

在python3.5中

>>> min(timeit.repeat(lambda: {**x, **y}))
0.4094954460160807
>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.7881555100320838
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.4525277839857154
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items()))))
2.3143140770262107
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
3.2069112799945287

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
linux系统使用python监测网络接口获取网络的输入输出
Jan 15 Python
Python 提取dict转换为xml/json/table并输出的实现代码
Aug 28 Python
Python中使用haystack实现django全文检索搜索引擎功能
Aug 26 Python
python将一个英文语句以单词为单位逆序排放的方法
Dec 20 Python
详解numpy.meshgrid()方法使用
Aug 01 Python
Python面向对象封装操作案例详解 II
Jan 02 Python
pytorch 模型的train模式与eval模式实例
Feb 20 Python
在Windows上安装和配置 Jupyter Lab 作为桌面级应用程序教程
Apr 22 Python
解决python父线程关闭后子线程不关闭问题
Apr 25 Python
Python转换字典成为对象,可以用&quot;.&quot;方式访问对象属性实例
May 11 Python
解决python cv2.imread 读取中文路径的图片返回为None的问题
Jun 02 Python
Python通过m3u8文件下载合并ts视频的操作
Apr 16 Python
Python中使用多进程来实现并行处理的方法小结
Aug 09 #Python
Python基于matplotlib绘制栈式直方图的方法示例
Aug 09 #Python
Python2.7编程中SQLite3基本操作方法示例
Aug 09 #Python
Django 前后台的数据传递的方法
Aug 08 #Python
关于python pyqt5安装失败问题的解决方法
Aug 08 #Python
利用Python自带PIL库扩展图片大小给图片加文字描述的方法示例
Aug 08 #Python
利用python打印出菱形、三角形以及矩形的方法实例
Aug 08 #Python
You might like
How to Auto Include a Javascript File
2007/02/02 Javascript
jquery 操作单选框,复选框,下拉列表实现代码
2009/10/27 Javascript
javascript 混合的构造函数和原型方式,动态原型方式
2009/12/07 Javascript
Javascript 面向对象(二)封装代码
2012/05/23 Javascript
jQuery的animate函数学习记录
2014/08/08 Javascript
JQuery限制复选框checkbox可选中个数的方法
2015/04/20 Javascript
nodejs调用cmd命令实现复制目录
2015/05/04 NodeJs
AngularJS辅助库browserTrigger用法示例
2016/11/03 Javascript
JS实现一个简单的日历
2017/02/22 Javascript
js实现颜色阶梯渐变效果(Gradient算法)
2017/03/21 Javascript
使用Bootstrap打造特色进度条效果
2017/05/02 Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
2017/08/19 Javascript
javaScript之split与join的区别(详解)
2017/11/08 Javascript
使用veloticy-ui生成文字动画效果
2018/02/08 Javascript
bootstrap table实现合并单元格效果
2018/12/24 Javascript
微信小程序页面上下滚动效果
2020/11/18 Javascript
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
2019/09/17 Javascript
JS在Array数组中按指定位置删除或添加元素对象方法示例
2019/11/19 Javascript
JS document form表单元素操作完整示例
2020/01/13 Javascript
[04:17]DOTA2完美盛典,rOtk、BurNIng携手巴图演唱《倔强》
2017/11/28 DOTA
python中的实例方法、静态方法、类方法、类变量和实例变量浅析
2014/04/26 Python
Python中使用glob和rmtree删除目录子目录及所有文件的例子
2014/11/21 Python
python数据处理实战(必看篇)
2017/06/11 Python
python实现简单点对点(p2p)聊天
2017/09/13 Python
python批量爬取下载抖音视频
2019/06/17 Python
pytorch 可视化feature map的示例代码
2019/08/20 Python
python实现超市商品销售管理系统
2019/11/22 Python
Python之字典添加元素的几种方法
2020/09/30 Python
详解pandas映射与数据转换
2021/01/22 Python
浅析几个CSS3常用功能的写法
2014/06/05 HTML / CSS
基于HTML5代码实现折叠菜单附源码下载
2015/11/27 HTML / CSS
全世界最美丽的四星和五星级酒店预订:Prestigia.com
2017/11/15 全球购物
Hotels.com拉丁美洲:从豪华酒店到经济型酒店的预定优惠和折扣
2019/12/09 全球购物
电子信息毕业生自荐信
2013/11/16 职场文书
企业法人授权委托书
2014/04/03 职场文书
2014年班主任自我评价范文
2014/04/23 职场文书