Skip to main content
 首页 » 编程设计

python之合并字典保留旧键和新值

2025年05月04日15qq78292959

我正在编写一个解析 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'} 

这是我目前的尝试:

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 

这行得通,但在我看来可能还有更好或更聪明的方法。

编辑:如果您想测试您的功能:

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'} 

编辑 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 

我觉得这很令人惊讶,因为我没想到字典 View 方法会慢得多。

请您参考如下方法:

字典有 dictionary view objects充当集合。使用这些来获得新旧之间的交集:

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 

以上使用 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 

以上代码以 new 中的所有键值对作为起点,然后为出现在两者中的任何键添加 old 的值。

演示:

>>> merge_preserving_old_values_and_new_keys(old, new) 
{'c': 3, 'e': 'z', 'd': 'y'} 

请注意,该函数与您的版本一样,会生成一个新字典(尽管键和值对象是共享的;它是一个浅拷贝)。

如果您不需要新字典来做其他任何事情,您也可以就地更新新字典:

def merge_preserving_old_values_and_new_keys(old, new): 
    new.update((k, old[k]) for k in old.viewkeys() & new.viewkeys()) 
    return new 

您还可以使用单行字典理解来构建新字典:

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()}