我想将两个词典融入一个新的词典。
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) 的值。
当前回答
您可以使用 toolz.merge([x, y]) 为此。
其他回答
我很想知道我能否用一行严格的方法击败接受答案的时间:
我尝试了5种方法,前面没有一个 - 所有一个线路 - 所有产生正确的答案 - 我无法接近。
所以......为了拯救你麻烦,也许满足好奇心:
import json
import yaml
import time
from ast import literal_eval as literal
def merge_two_dicts(x, y):
z = x.copy() # start with x's keys and values
z.update(y) # modifies z with y's keys and values & returns None
return z
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
start = time.time()
for i in range(10000):
z = yaml.load((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify yaml')
start = time.time()
for i in range(10000):
z = literal((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify literal')
start = time.time()
for i in range(10000):
z = eval((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify eval')
start = time.time()
for i in range(10000):
z = {k:int(v) for k,v in (dict(zip(
((str(x)+str(y))
.replace('}',' ')
.replace('{',' ')
.replace(':',' ')
.replace(',',' ')
.replace("'",'')
.strip()
.split(' '))[::2],
((str(x)+str(y))
.replace('}',' ')
.replace('{',' ').replace(':',' ')
.replace(',',' ')
.replace("'",'')
.strip()
.split(' '))[1::2]
))).items()}
elapsed = (time.time()-start)
print (elapsed, z, 'stringify replace')
start = time.time()
for i in range(10000):
z = json.loads(str((str(x)+str(y)).replace('}{',', ').replace("'",'"')))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify json')
start = time.time()
for i in range(10000):
z = merge_two_dicts(x, y)
elapsed = (time.time()-start)
print (elapsed, z, 'accepted')
结果:
7.693928956985474 {'c': 11, 'b': 10, 'a': 1} stringify yaml
0.29134678840637207 {'c': 11, 'b': 10, 'a': 1} stringify literal
0.2208399772644043 {'c': 11, 'b': 10, 'a': 1} stringify eval
0.1106564998626709 {'c': 11, 'b': 10, 'a': 1} stringify replace
0.07989692687988281 {'c': 11, 'b': 10, 'a': 1} stringify json
0.005082368850708008 {'c': 11, 'b': 10, 'a': 1} accepted
我從這裡學到的是,JSON的方法是最快的方式(那些試圖)從字典的字典返回;比我認為是正常的方法的速度更快(約四分之一的時間)我也學到,YAML的方法應該以任何代價避免。
是的,我明白这不是最好的 / 正确的方式. 我很好奇它是否更快,而且不是; 我发表以证明它是这样。
一种替代:
z = x.copy()
z.update(y)
滥用导致马太福的答案的一个单词解决方案:
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (lambda f=x.copy(): (f.update(y), f)[1])()
>>> z
{'a': 1, 'c': 11, 'b': 10}
你说你想要一个表达式,所以我滥用了Lambda连接一个名字,而Tuples超越Lambda的单表达式限制。
当然,你也可以这样做,如果你不在乎复制它:
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (x.update(y), x)[1]
>>> z
{'a': 1, 'b': 10, 'c': 11}
在您的情况下,您可以:
z = dict(list(x.items()) + list(y.items()))
因此,如您所需,将最终定位定位为z,并使关键b的值由第二(y)定位的值正确上调:
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
如果您使用 Python 2, 您甚至可以删除列表() 通话。
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}
如果您使用 Python 版本 3.9.0a4 或更高版本,则可以直接使用:
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = x | y
print(z)
{'a': 1, 'c': 11, 'b': 10}
我想要一些类似的东西,但有能力说明双键中的值是如何合并的,所以我打破了这个(但没有重量测试)。
def merge(d1, d2, merge_fn=lambda x,y:y):
"""
Merges two dictionaries, non-destructively, combining
values on duplicate keys as defined by the optional merge
function. The default behavior replaces the values in d1
with corresponding values in d2. (There is no other generally
applicable merge strategy, but often you'll have homogeneous
types in your dicts, so specifying a merge technique can be
valuable.)
Examples:
>>> d1
{'a': 1, 'c': 3, 'b': 2}
>>> merge(d1, d1)
{'a': 1, 'c': 3, 'b': 2}
>>> merge(d1, d1, lambda x,y: x+y)
{'a': 2, 'c': 6, 'b': 4}
"""
result = dict(d1)
for k,v in d2.iteritems():
if k in result:
result[k] = merge_fn(result[k], v)
else:
result[k] = v
return result