我想将两个词典融入一个新的词典。
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) 的值。
当前回答
在这里和其他地方绘制想法,我已经理解了一个功能:
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。
其他回答
此外,当您使用.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中添加,而复制()和更新()将在较旧版本中工作。
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z
对于两个字典中的关键物品(“b”),您可以通过将最后一个放在输出中来控制哪个。
在您的情况下,您可以:
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}
z1 = dict(x.items() + y.items())
z2 = dict(x, **y)
在我的机器上,至少(一个相当常见的x86_64运行Python 2.5.2),替代Z2不仅更短,更简单,而且更快。
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z1=dict(x.items() + y.items())'
100000 loops, best of 3: 5.67 usec per loop
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z2=dict(x, **y)'
100000 loops, best of 3: 1.53 usec per loop
示例2:不超越的字典,将252条短线地图到整条,反之亦然:
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z1=dict(x.items() + y.items())'
1000 loops, best of 3: 260 usec per loop
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z2=dict(x, **y)'
10000 loops, best of 3: 26.9 usec per loop
z2赢得了大约10的因素,这在我的书中是一个相当大的胜利!
在比较这两个之后,我想知道 z1 的不良性能是否可以归功于构建两个项目列表的顶端,这反过来导致我想知道这个变量是否会更好地工作:
from itertools import chain
z3 = dict(chain(x.iteritems(), y.iteritems()))
% python -m timeit -s 'from itertools import chain; from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z3=dict(chain(x.iteritems(), y.iteritems()))'
10000 loops, best of 3: 66 usec per loop
z0 = dict(x)
z0.update(y)
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z0=dict(x); z0.update(y)'
10000 loops, best of 3: 26.9 usec per loop
你也可以这样写作
z0 = x.copy()
z0.update(y)
正如托尼所做的那样,但(不令人惊讶)评分的差异显然没有对性能的测量效应。 使用任何人看起来对你是正确的。
最好的版本我可以想象,而不使用复制将是:
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的值,但我不认为很难找到它。