3

我希望有效地合并两个(相当随意的)数据结构:一个代表一组默认值,一个代表覆盖。下面的示例数据。(天真地迭代结构是可行的,但速度很慢。)关于处理这种情况的最佳方法的想法?

_DEFAULT = {'A':1122,'B':1133,'C':[9988,{'E':[{'F':6666,},],},],}

_OVERRIDE1 = {'B':1234,'C':[9876,{'D':2345,'E':[{'F':6789,'G':9876,},1357,],},] , }
_ANSWER1 = {'A':1122,'B':1234,'C':[9876,{'D':2345,'E':[{'F':6789,'G':9876,},1357 , ], }, ], }

_OVERRIDE2 = {'C':[6543,{'E':[{'G':9876,},],},],}
_ANSWER2 = {'A':1122,'B':1133,'C':[6543,{'E':[{'F':6666,'G':9876,},],},],}

_OVERRIDE3 = {'B':3456,'C':[1357,{'D':4567,'E':[{'F':6677,'G':9876,},2468,],},] , }
_ANSWER3 = {'A':1122,'B':3456,'C':[1357,{'D':4567,'E':[{'F':6677,'G':9876,},2468 , ], }, ], }

这是如何运行测试的示例:(字典更新不起作用,只是一个存根函数。)

    导入迭代工具

    def mergeStuff(默认,覆盖):
        # 这不起作用
        结果 = 字典(默认)
        结果.更新(覆盖)
        返回结果

    定义主():
        对于覆盖,在 itertools.izip(_OVERRIDES, _ANSWERS) 中回答:
           结果 = mergeStuff(_DEFAULT,覆盖)
           print('ANSWER: %s' % (answer) )
           print('结果:%s\n' % (结果) )

4

4 回答 4

4

你不能通过“迭代”来做到这一点,你需要一个这样的递归例程:

def merge(a, b):
    if isinstance(a, dict) and isinstance(b, dict):
        d = dict(a)
        d.update({k: merge(a.get(k, None), b[k]) for k in b})
        return d

    if isinstance(a, list) and isinstance(b, list):
        return [merge(x, y) for x, y in itertools.izip_longest(a, b)]

    return a if b is None else b
于 2013-10-15T10:25:10.557 回答
3

如果您希望您的代码快速,请不要疯狂复制

你真的不需要合并两个字典。你可以把它们锁起来。

提供了一个 ChainMap 类用于快速链接多个映射,因此它们可以被视为一个单元。它通常比创建新字典和运行多个 update() 调用要快得多。

class ChainMap(UserDict.DictMixin):
"""Combine multiple mappings for sequential lookup"""

    def __init__(self, *maps):
        self._maps = maps

    def __getitem__(self, key):
        for mapping in self._maps:
            try:
                return mapping[key]
            except KeyError:
                pass
        raise KeyError(key)

def main():
    for override, answer in itertools.izip( _OVERRIDES, _ANSWERS ):
       result = ChainMap(override, _DEFAULT)
于 2013-10-15T10:40:47.253 回答
0

dict.update()是你需要的。但它会覆盖原始字典,因此如果要保留它,请复制原始字典。

于 2013-10-15T10:02:47.443 回答
0

如果您知道一个结构始终是另一个结构的子集,那么只需迭代超集并在 O(n) 时间内您可以逐个元素检查它是否存在于子集中,如果不存在,则将其放在那里。据我所知,除了手动逐个元素地检查之外,没有什么神奇的方法可以做到这一点。正如我所说,这还不错,因为它可以用 O(n) 复杂度来完成。

于 2013-10-15T09:56:53.227 回答