Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 保留旧键和新值的合并词典_Python_Dictionary - Fatal编程技术网

Python 保留旧键和新值的合并词典

Python 保留旧键和新值的合并词典,python,dictionary,Python,Dictionary,我正在编写一个Python脚本来解析RSS提要。我想维护一个定期更新的提要条目字典。应该删除提要中不再存在的条目,新条目应该获得默认值,以前看到的条目的值应该保持不变 这最好用例子来解释,我认为: >>> old = { ... 'a': 1, ... 'b': 2, ... 'c': 3 ... } >>> new = { ... 'c': 'x', ... 'd': 'y', ... 'e': 'z' ...

我正在编写一个Python脚本来解析RSS提要。我想维护一个定期更新的提要条目字典。应该删除提要中不再存在的条目,新条目应该获得默认值,以前看到的条目的值应该保持不变

这最好用例子来解释,我认为:

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

我觉得这很奇怪,因为我没想到dictionary-view方法会慢得多。

这应该更有效,因为您不再遍历整个old.items。此外,由于没有覆盖某些值,因此更清楚地知道您试图以这种方式做什么

for k, v in new.items():
    if k in old.keys():
      out[k] = old[k]
    else:
      out[k] = v
return out

这应该更有效,因为您不再遍历整个old.items。此外,由于没有覆盖某些值,因此更清楚地知道您试图以这种方式做什么

for k, v in new.items():
    if k in old.keys():
      out[k] = old[k]
    else:
      out[k] = v
return out
字典有集的作用。使用这些选项可以获得新旧之间的交点:

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
上面使用了Python2语法;如果使用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的值

演示:

请注意,该函数与您的版本一样,会生成一个新的字典,尽管键和值对象是共享的;这是一个肤浅的副本

如果您不需要新词典来做任何其他事情,您也可以在适当的位置更新新词典:

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()}
字典有集的作用。使用这些选项可以获得新旧之间的交点:

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
上面使用了Python2语法;如果使用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的值

演示:

请注意,该函数与您的版本一样,会生成一个新的字典,尽管键和值对象是共享的;这是一个肤浅的副本

如果您不需要新词典来做任何其他事情,您也可以在适当的位置更新新词典:

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

我不是100%将这些信息添加到讨论中的最佳方式:如有必要,请随意编辑/重新发布

下面是这里讨论的所有方法的计时结果

from timeit import timeit

def loop_merge(old, new):
    out = {}
    for k, v in new.items():
        if k in old:
            out[k] = old[k]
        else:
                out[k] = v
    return out

def set_merge(old, new):
    out = new.copy()
    out.update((k, old[k]) for k in old.keys() & new.keys())
    return out

def comp_merge(old, new):
    return {k: old[k] if k in old else v for k, v in new.items()}

def orig_merge(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


old = {'a': 1, 'b': 2, 'c': 3}
new = {'c': 'x', 'd': 'y', 'e': 'z'}
out = {'c': 3, 'd': 'y', 'e': 'z'}

assert loop_merge(old, new) == out
assert set_merge(old, new) == out
assert comp_merge(old, new) == out
assert orig_merge(old, new) == out

setup = """
from __main__ import old, new, loop_merge, set_merge, comp_merge, orig_merge
"""

for a in ['loop', 'set', 'comp', 'orig']:
    time = timeit('{}_merge(old, new)'.format(a), setup=setup)
    print('{}: {}'.format(a, time))

size = 10**4
large_old = {i: 'old' for i in range(size)}
large_new = {i: 'new' for i in range(size//2, size)}

setup = """
from __main__ import large_old, large_new, loop_merge, set_merge, comp_merge, orig_merge
"""

for a in ['loop', 'set', 'comp', 'orig']:
    time = timeit('{}_merge(large_old, large_new)'.format(a), setup=setup)
    print('{}: {}'.format(a, time))
优胜者是改进的循环方法

$ python3 merge.py
loop: 0.7791572390015062  # small dictionaries
set: 3.1920828100010112
comp: 1.1180207730030816
orig: 1.1681104259987478
loop: 927.2149353210007  # large dictionaries
set: 1696.8342713210004
comp: 902.039078668
orig: 1373.0389542560006
我很失望,因为dictionary view/set操作方法要酷得多


对于较大的词典10^4项,词典理解方法领先于改进的循环方法,远远领先于原始方法。设置操作方法的执行速度仍然最慢。

我不是100%将此信息添加到讨论中的最佳方法:如有必要,请随意编辑/重新发布

下面是这里讨论的所有方法的计时结果

from timeit import timeit

def loop_merge(old, new):
    out = {}
    for k, v in new.items():
        if k in old:
            out[k] = old[k]
        else:
                out[k] = v
    return out

def set_merge(old, new):
    out = new.copy()
    out.update((k, old[k]) for k in old.keys() & new.keys())
    return out

def comp_merge(old, new):
    return {k: old[k] if k in old else v for k, v in new.items()}

def orig_merge(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


old = {'a': 1, 'b': 2, 'c': 3}
new = {'c': 'x', 'd': 'y', 'e': 'z'}
out = {'c': 3, 'd': 'y', 'e': 'z'}

assert loop_merge(old, new) == out
assert set_merge(old, new) == out
assert comp_merge(old, new) == out
assert orig_merge(old, new) == out

setup = """
from __main__ import old, new, loop_merge, set_merge, comp_merge, orig_merge
"""

for a in ['loop', 'set', 'comp', 'orig']:
    time = timeit('{}_merge(old, new)'.format(a), setup=setup)
    print('{}: {}'.format(a, time))

size = 10**4
large_old = {i: 'old' for i in range(size)}
large_new = {i: 'new' for i in range(size//2, size)}

setup = """
from __main__ import large_old, large_new, loop_merge, set_merge, comp_merge, orig_merge
"""

for a in ['loop', 'set', 'comp', 'orig']:
    time = timeit('{}_merge(large_old, large_new)'.format(a), setup=setup)
    print('{}: {}'.format(a, time))
优胜者是改进的循环方法

$ python3 merge.py
loop: 0.7791572390015062  # small dictionaries
set: 3.1920828100010112
comp: 1.1180207730030816
orig: 1.1681104259987478
loop: 927.2149353210007  # large dictionaries
set: 1696.8342713210004
comp: 902.039078668
orig: 1373.0389542560006
我很失望,因为dictionary view/set操作方法要酷得多


对于较大的词典10^4项,词典理解方法领先于改进的循环方法,远远领先于原始方法。设置操作方法的执行速度仍然最慢。

这会改变原有的新操作。不要在dict.keys中使用if键;在Python2中,每次通过循环创建一个全新的list对象,然后扫描该列表以查看键是否在其中。在Python3中,每次都创建一个dictionary视图对象,然后进行O1常量时间成员身份测试。所有这一切都比仅仅键入dict要昂贵,因此放弃.keys调用,该调用在不创建新对象的情况下执行O1测试。这会改变新的位置。不要在dict.keys中使用if-key;在Python2中,每次通过循环创建一个全新的list对象,然后扫描该列表以查看键是否在其中。在Python3中,每次都创建一个dictionary视图对象,然后进行O1常量时间成员身份测试。所有这些都比只键入dict要昂贵,因此放弃.keys调用,它在不创建新对象的情况下执行O1测试。这确实更清晰,而且肯定是对我尝试的改进!missing:out={}此处相同:不要在dict.keys中使用if键;在Python2中,每次通过循环创建一个全新的list对象,然后扫描该列表以查看键是否在其中。在Python3中,每次创建一个dictionary视图对象,然后创建一个O1常量时间memb
完成了ership测试。所有这一切都比只键入dict要昂贵,因此放弃.keys调用,该调用在不创建新对象的情况下执行O1测试。事实上,@MartijnPieters,删除.keys会将我的时间从~1.2更改为0.8。这确实更清晰,而且肯定是对我尝试的改进!missing:out={}此处相同:不要在dict.keys中使用if键;在Python2中,每次通过循环创建一个全新的list对象,然后扫描该列表以查看键是否在其中。在Python3中,每次都创建一个dictionary视图对象,然后进行O1常量时间成员身份测试。所有这些都比只键入dict要昂贵,因此放弃.keys调用,该调用在不创建新对象的情况下执行O1测试。事实上,@MartijnPieters,删除.keys会改变我的时间,它的结果从~1.2变为0.8。输入字典相当小。大的输入会发生什么?有趣;我期望dict comp比普通循环更好,dict view结果令人失望,但实际上并不令人惊讶,因为它们将普通循环与字典副本相结合。输入字典相当小。大的输入会发生什么?有趣;我期望dict comp比普通循环更好,dict view结果令人失望,但实际上并不令人惊讶,因为它们将普通循环与字典副本结合起来。