我正在编写一个解析 RSS 提要的 Python 脚本。我想维护一个定期更新的提要条目字典。提要中不再存在的条目应被删除,新条目应获得默认值,并且以前看到的条目的值应保持不变。
我认为最好通过例子来解释:
>>> old = {
... 'a': 1,
... 'b': 2,
... 'c': 3
... }
>>> new = {
... 'c': 'x',
... 'd': 'y',
... 'e': 'z'
... }
>>> out = some_function(old, new)
>>> out
{'c': 3, 'd': 'y', 'e': 'z'}
Run Code Online (Sandbox Code Playgroud)
这是我目前的尝试:
def merge_preserving_old_values_and_new_keys(old, new):
out = {}
for k, v in new.items():
out[k] = v
for k, v in old.items():
if k in out:
out[k] = v
return out
Run Code Online (Sandbox Code Playgroud)
这可行,但在我看来可能有更好或更聪明的方法。
编辑:如果您想测试您的功能:
def my_merge(old, new):
pass
old = {'a': 1, 'b': 2, 'c': 3}
new = {'c': 'x', 'd': 'y', 'e': 'z'}
out = my_merge(old, new)
assert out == {'c': 3, 'd': 'y', 'e': 'z'}
Run Code Online (Sandbox Code Playgroud)
编辑2:将 Martijn Pieters 的答案定义为set_merge,bravosierra99 的答案定义为loop_merge,我的第一次尝试定义为orig_merge,我得到以下计时结果:
>>> setup="""
... old = {'a': 1, 'b': 2, 'c': 3}
... new = {'c': 'x', 'd': 'y', 'e': 'z'}
... from __main__ import set_merge, loop_merge, orig_merge
... """
>>> timeit.timeit('set_merge(old, new)', setup=setup)
3.4415210600000137
>>> timeit.timeit('loop_merge(old, new)', setup=setup)
1.161155690000669
>>> timeit.timeit('orig_merge(old, new)', setup=setup)
1.1776735319999716
Run Code Online (Sandbox Code Playgroud)
我觉得这很令人惊讶,因为我没想到字典视图方法会慢得多。
字典具有充当集合的字典视图对象。使用这些来获取新旧之间的交集:
def merge_preserving_old_values_and_new_keys(old, new):
result = new.copy()
result.update((k, old[k]) for k in old.viewkeys() & new.viewkeys())
return result
Run Code Online (Sandbox Code Playgroud)
上面使用了Python 2语法;如果您使用的是 Python 3,请使用old.keys() & new.keys()以下命令以获得相同的结果:
def merge_preserving_old_values_and_new_keys(old, new):
# Python 3 version
result = new.copy()
result.update((k, old[k]) for k in old.keys() & new.keys())
return result
Run Code Online (Sandbox Code Playgroud)
上面的代码以所有键值对new为起点,然后添加old出现在两者中的任何键的值。
演示:
>>> merge_preserving_old_values_and_new_keys(old, new)
{'c': 3, 'e': 'z', 'd': 'y'}
Run Code Online (Sandbox Code Playgroud)
请注意,该函数与您的版本一样,会生成一个新字典(尽管键和值对象是共享的;它是浅表副本)。
如果您不需要新字典做其他任何事情,您也可以就地更新新字典:
def merge_preserving_old_values_and_new_keys(old, new):
new.update((k, old[k]) for k in old.viewkeys() & new.viewkeys())
return new
Run Code Online (Sandbox Code Playgroud)
您还可以使用单行字典理解来构建一本新字典:
def merge_preserving_old_values_and_new_keys(old, new):
return {k: old[k] if k in old else v for k, v in new.items()}
Run Code Online (Sandbox Code Playgroud)