检查Python dicts是否具有相同的形状和键

tsc*_*zle 6 python dictionary

对于单层dicts x = {'a': 1, 'b': 2},问题很容易,并在SO上回答(Pythonic方式检查两个字典是否有相同的键集?)但是嵌套dicts呢?

例如,y = {'a': {'c': 3}, 'b': {'d': 4}}有键'a','b'但我想将其形状与另一个嵌套的dict结构进行比较z = {'a': {'c': 5}, 'b': {'d': 6}},因为它具有相同的形状和键(不同的值很好)y.w = {'a': {'c': 3}, 'b': {'e': 4}}会有键'a','b'但在它的下一层不同,y因为w['b']有键'e'y['b']有键'd'.

想的两个参数的短/简单的功能dict_1dict_2并返回True,如果他们有,如上所述,以及相同的形状和键False除外.

nne*_*neo 7

这提供了两个被删除任何非字典值的字典的副本,然后比较它们:

def getshape(d):
    if isinstance(d, dict):
        return {k:getshape(d[k]) for k in d}
    else:
        # Replace all non-dict values with None.
        return None

def shape_equal(d1, d2):
    return getshape(d1) == getshape(d2)
Run Code Online (Sandbox Code Playgroud)


Aar*_*all 5

我喜欢nneonneo的答案,它应该相对较快,但我想要一些不会产生额外不必要的数据结构的东西(我一直在学习Python中的内存碎片).这可能会也可能不会更快或更快.

(编辑:剧透!)

通过足够好的余量使其在所有情况下都更可取,请参阅其他分析答案.

但是如果处理大量的这些并且存在内存问题,那么以这种方式进行操作可能更为可取.

履行

这应该工作在Python 3,也许2.7如果你翻译keysviewkeys,绝对不是2.6.它依赖于dicts具有的键的集合视图:

def sameshape(d1, d2):
    if isinstance(d1, dict):
        if isinstance(d2, dict):
            # then we have shapes to check
            return (d1.keys() == d2.keys() and
                    # so the keys are all the same
                    all(sameshape(d1[k], d2[k]) for k in d1.keys()))
                    # thus all values will be tested in the same way.
        else:
            return False # d1 is a dict, but d2 isn't
    else:
        return not isinstance(d2, dict) # if d2 is a dict, False, else True.
Run Code Online (Sandbox Code Playgroud)

编辑更新以减少冗余类型检查,现在更加高效.

测试

去检查:

print('expect false:')
print(sameshape({'foo':{'bar':{None:None}}}, {'foo':{'bar':{None: {} }}}))
print('expect true:')
print(sameshape({'foo':{'bar':{None:None}}}, {'foo':{'bar':{None:'foo'}}}))
print('expect false:')
print(sameshape({'foo':{'bar':{None:None}}}, {'foo':{'bar':{None:None, 'baz':'foo'}}}))
Run Code Online (Sandbox Code Playgroud)

打印:

expect false:
False
expect true:
True
expect false:
False
Run Code Online (Sandbox Code Playgroud)