我想将两个词典融入一个新的词典。

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge(x, y)

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

每当两个字典中都有一个关键 k 时,只应保留 y(k) 的值。


当前回答

我很想知道我能否用一行严格的方法击败接受答案的时间:

我尝试了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的方法應該以任何代價避免。

是的,我明白这不是最好的 / 正确的方式. 我很好奇它是否更快,而且不是; 我发表以证明它是这样。

其他回答

此外,当您使用.items() (Python 3.0 之前),您正在创建一个新的列表,包含从字典中的项目. 如果您的字典是大,那么它是相当多的顶部(两个大列表将被扔掉,一旦合并的字典创建)。更新() 可以更有效地工作,因为它可以通过第二个字典项目为项目。

在时间方面:

>>> timeit.Timer("dict(x, **y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.52571702003479
>>> timeit.Timer("temp = x.copy()\ntemp.update(y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.694622993469238
>>> timeit.Timer("dict(x.items() + y.items())", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
41.484580039978027

此外,字典创建的关键词论点仅在Python 2.3中添加,而复制()和更新()将在较旧版本中工作。

最好的版本我可以想象,而不使用复制将是:

from itertools import chain
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
dict(chain(x.iteritems(), y.iteritems()))

它比 dict(x.items() + y.items()) 更快,但不像 n = copy(a); n.update(b),至少在 CPython 上。

我个人最喜欢这个版本,因为它在一个单一的功能合成中描述了我想要的东西相当好,唯一的小问题是,它并不完全显而易见,Y的值超过X的值,但我不认为很难找到它。

在Python 3.8发布时,将有一个新的选项(计划于2019年10月20日),感谢PEP 572:分配表达式。 新的分配表达式操作员:= 允许您分配副本的结果,并且仍然使用它来呼叫更新,留下组合代码一个单一表达式,而不是两个陈述,改变:

newdict = dict1.copy()
newdict.update(dict2)

到:

(newdict := dict1.copy()).update(dict2)

(newdict := dict1.copy()).update(dict2) or newdict

newdict = {**dict1, **dict2}

脱包方法更清晰(对于任何人都知道一般的脱包,首先,你应该),不需要一个名字的结果(因此,它是更紧密的,当构建一个暂时的,即时转移到一个功能或包含在一个名单 / 双字或类似),并且几乎肯定更快,也是(在CPython上)相当于:

newdict = {}
newdict.update(dict1)
newdict.update(dict2)

它也更可扩展,因为结合三个法则是显而易见的:

 newdict = {**dict1, **dict2, **dict3}

 (newdict := dict1.copy()).update(dict2), newdict.update(dict3)

或沒有暫時的九個,但以真實的測試,每個九個結果:

 (newdict := dict1.copy()).update(dict2) or newdict.update(dict3)

def dict_merge(a, b):
  c = a.copy()
  c.update(b)
  return c

new = dict_merge(old, extras)

在如此阴影和可疑的答案中,这个闪发光的例子是在Python中合并独裁的唯一和唯一好的方式,由独裁者为生活Guido van Rossum自己支持! 另一个人提出了一半,但没有把它放在一个功能上。

print dict_merge(
      {'color':'red', 'model':'Mini'},
      {'model':'Ferrari', 'owner':'Carl'})

给了:

{'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}

我很想知道我能否用一行严格的方法击败接受答案的时间:

我尝试了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的方法應該以任何代價避免。

是的,我明白这不是最好的 / 正确的方式. 我很好奇它是否更快,而且不是; 我发表以证明它是这样。