我想将两个词典融入一个新的词典。
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) 的值。
当前回答
如果你認為Lambdas是壞的,那麼不要再閱讀。 如要求,你可以用一個表達寫下快速和記憶效益的解決方案:
x = {'a':1, 'b':2}
y = {'b':10, 'c':11}
z = (lambda a, b: (lambda a_copy: a_copy.update(b) or a_copy)(a.copy()))(x, y)
print z
{'a': 1, 'c': 11, 'b': 10}
print x
{'a': 1, 'b': 2}
如上所述,使用两行或写一个函数可能是一个更好的方式去。
其他回答
我很想知道我能否用一行严格的方法击败接受答案的时间:
我尝试了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的方法應該以任何代價避免。
是的,我明白这不是最好的 / 正确的方式. 我很好奇它是否更快,而且不是; 我发表以证明它是这样。
您可以使用 toolz.merge([x, y]) 为此。
另一个,更细致的选择:
z = dict(x, **y)
注意:这已成为一个受欢迎的答案,但重要的是要指出的是,如果 y 有任何不紧密的密钥,事实上,这完全是CPython实施细节的滥用,并且它不在Python 3或PyPy,IronPython,或Jython工作。
我想要一些类似的东西,但有能力说明双键中的值是如何合并的,所以我打破了这个(但没有重量测试)。
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
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> x, z = dict(x), x.update(y) or x
>>> x
{'a': 1, 'b': 2}
>>> y
{'c': 11, 'b': 10}
>>> z
{'a': 1, 'c': 11, 'b': 10}