我想将两个词典融入一个新的词典。
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge(x, y)
>>> z
{'a': 1, 'b': 3, 'c': 4}
每当两个字典中都有一个关键 k 时,只应保留 y(k) 的值。
我想将两个词典融入一个新的词典。
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge(x, y)
>>> z
{'a': 1, 'b': 3, 'c': 4}
每当两个字典中都有一个关键 k 时,只应保留 y(k) 的值。
当前回答
这个问题被标签为Python-3x,但考虑到这是一个相对较新的补充,并且最受欢迎的,接受的答案与Python 2.x解决方案广泛处理,我敢添加一个线条,引用一个令人兴奋的功能的Python 2.x列表理解,即名字泄漏。
$ python2
Python 2.7.13 (default, Jan 19 2017, 14:48:08)
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> [z.update(d) for z in [{}] for d in (x, y)]
[None, None]
>>> z
{'a': 1, 'c': 11, 'b': 10}
>>> ...
我很高兴说上面的内容不再在任何Python 3版本上工作。
其他回答
这个问题被标签为Python-3x,但考虑到这是一个相对较新的补充,并且最受欢迎的,接受的答案与Python 2.x解决方案广泛处理,我敢添加一个线条,引用一个令人兴奋的功能的Python 2.x列表理解,即名字泄漏。
$ python2
Python 2.7.13 (default, Jan 19 2017, 14:48:08)
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> [z.update(d) for z in [{}] for d in (x, y)]
[None, None]
>>> z
{'a': 1, 'c': 11, 'b': 10}
>>> ...
我很高兴说上面的内容不再在任何Python 3版本上工作。
在Python3中,项目方法不再返回一个列表,而是一个视图,它像一个集一样作用。
dict(x.items() | y.items())
dict(x.viewitems() | y.viewitems())
编辑:
首先,请注意,在 Python 3 中, dic(x、 **y) 技巧不会工作,除非 y 中的键是线条。
此外,Raymond Hettinger的链路图答案是相当优雅的,因为它可以作为论点采取任意数量的论点,但从论点看起来它顺序地通过每个搜索的所有论点的列表:
In [1]: from collections import ChainMap
In [2]: from string import ascii_uppercase as up, ascii_lowercase as lo; x = dict(zip(lo, up)); y = dict(zip(up, lo))
In [3]: chainmap_dict = ChainMap(y, x)
In [4]: union_dict = dict(x.items() | y.items())
In [5]: timeit for k in union_dict: union_dict[k]
100000 loops, best of 3: 2.15 µs per loop
In [6]: timeit for k in chainmap_dict: chainmap_dict[k]
10000 loops, best of 3: 27.1 µs per loop
我是 Chainmap 的粉丝,但看起来不太实用,在那里可能有很多搜索。
另一个,更细致的选择:
z = dict(x, **y)
注意:这已成为一个受欢迎的答案,但重要的是要指出的是,如果 y 有任何不紧密的密钥,事实上,这完全是CPython实施细节的滥用,并且它不在Python 3或PyPy,IronPython,或Jython工作。
在这里和其他地方绘制想法,我已经理解了一个功能:
def merge(*dicts, **kv):
return { k:v for d in list(dicts) + [kv] for k,v in d.items() }
使用(在Python 3中测试):
assert (merge({1:11,'a':'aaa'},{1:99, 'b':'bbb'},foo='bar')==\
{1: 99, 'foo': 'bar', 'b': 'bbb', 'a': 'aaa'})
assert (merge(foo='bar')=={'foo': 'bar'})
assert (merge({1:11},{1:99},foo='bar',baz='quux')==\
{1: 99, 'foo': 'bar', 'baz':'quux'})
assert (merge({1:11},{1:99})=={1: 99})
你可以用Lambda。
在 Python 3.9 中
基于PEP 584的,Python的新版本引入了两个新的词典操作器:union(<unk>)和in-place union(<unk>=)。您可以使用<unk>来结合两个词典,而<unk>=将更新一个词典:
>>> pycon = {2016: "Portland", 2018: "Cleveland"}
>>> europython = {2017: "Rimini", 2018: "Edinburgh", 2019: "Basel"}
>>> pycon | europython
{2016: 'Portland', 2018: 'Edinburgh', 2017: 'Rimini', 2019: 'Basel'}
>>> pycon |= europython
>>> pycon
{2016: 'Portland', 2018: 'Edinburgh', 2017: 'Rimini', 2019: 'Basel'}
使用<unk>的优点之一是它在不同的字典类型上工作,并通过合并保持类型:
>>> from collections import defaultdict
>>> europe = defaultdict(lambda: "", {"Norway": "Oslo", "Spain": "Madrid"})
>>> africa = defaultdict(lambda: "", {"Egypt": "Cairo", "Zimbabwe": "Harare"})
>>> europe | africa
defaultdict(<function <lambda> at 0x7f0cb42a6700>,
{'Norway': 'Oslo', 'Spain': 'Madrid', 'Egypt': 'Cairo', 'Zimbabwe': 'Harare'})
>>> {**europe, **africa}
{'Norway': 'Oslo', 'Spain': 'Madrid', 'Egypt': 'Cairo', 'Zimbabwe': 'Harare'}
您可以使用默认定义,当您想要有效处理丢失的密钥时,请注意, <unk> 保留默认定义,而 {**europe, **africa} 不。
基本用途是更新现有字典,类似于.update():
>>> libraries = {
... "collections": "Container datatypes",
... "math": "Mathematical functions",
... }
>>> libraries |= {"zoneinfo": "IANA time zone support"}
>>> libraries
{'collections': 'Container datatypes', 'math': 'Mathematical functions',
'zoneinfo': 'IANA time zone support'}
当您将字典与字典合并时,两个字典都必须具有适当的字典类型,另一方面,现场运营商(字典=)很高兴与任何字典类似的数据结构合作:
>>> libraries |= [("graphlib", "Functionality for graph-like structures")]
>>> libraries
{'collections': 'Container datatypes', 'math': 'Mathematical functions',
'zoneinfo': 'IANA time zone support',
'graphlib': 'Functionality for graph-like structures'}