在另一个嵌套字典中比较一个嵌套字典的键和值

Compare key and values of one nested dictionary in other nested dictionary

我正在尝试递归比较以下两个 python 字典:

expectededr = {'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'attempted': {'smpp': {'registeredDelivery': 0}, 'status': 'success', 'OATON': 1, 'OANPI': 1, 'DATON': 1, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404'}, 'customerID': 'customer01', 'productID': 'product'}

edr = {'Category': 'NO', 'Type': 'mt', 'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'protocolID': 'smpp', 'direction': 'attempted', 'attempted': {'status': 'success', 'OANPI': 1, 'DATON': 1, 't2': 1512549691602, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404', 'smpp': {'fragmented': False, 'sequenceID': 1, 'registeredDelivery': 0, 'messageID': '4e7b48ad-b39e-4e91-a7bb-2de463e4a6ee', 'srcPort': 39417, 'messageType': 4, 'Status': 0, 'ESMClass': 0, 'dstPort': 0, 'size': 0}, 'OATON': 1, 'PID': 0, 't1': 1512549691602}, 'customerID': 'customer01', 'productID': 'product'}  

我正在尝试比较的方式是在第二个字典中查找和比较第一个字典的键和值,如果匹配则 print PASS 否则 print FAIL

for key in expectededr:
   if expectededr[key] == edr[key]:
       print("PASS")
   else:
       print("FAIL")

输出:

FAIL
PASS
PASS
PASS

上面的代码无法比较所有的键和值,因为它们是嵌套的字典。
正如您在下面看到的,如果我在上面打印键和值,我会看到它不会进入子字典并且缺少它们的键:

for key in expectededr:
    if expectededr[key] == edr[key]:
        print(expectededr[key])
        print(edr[key])

输出:

customer01
customer01
e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3
e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3
product
product

有人可以帮助更新此代码,以便我可以在这些嵌套词典中进行比较吗?

一种方法是将字典展平,然后比较键是否匹配。

所以让我们先初始化你的命令:

In [23]: expectededr = {'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'attempted': {'smpp': {'registeredDelivery': 0}, 'status': 'success', 'OATON': 1, 'OANP
    ...: I': 1, 'DATON': 1, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404'}, 'customerID': 'customer01', 'productID': 'product'}
    ...: 
    ...: edr = {'Category': 'NO', 'Type': 'mt', 'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'protocolID': 'smpp', 'direction': 'attempted', 'attempted': {'
    ...: status': 'success', 'OANPI': 1, 'DATON': 1, 't2': 1512549691602, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404', 'smpp': {'fragmented': False, '
    ...: sequenceID': 1, 'registeredDelivery': 0, 'messageID': '4e7b48ad-b39e-4e91-a7bb-2de463e4a6ee', 'srcPort': 39417, 'messageType': 4, 'Status': 0, 'ESMCl
    ...: ass': 0, 'dstPort': 0, 'size': 0}, 'OATON': 1, 'PID': 0, 't1': 1512549691602}, 'customerID': 'customer01', 'productID': 'product'}  
    ...: 

为了扁平化你的字典,我们可以使用 the approach suggested in Flatten nested Python dictionaries, compressing keys:

In [24]: import collections
    ...: 
    ...: def flatten(d, parent_key='', sep='_'):
    ...:     items = []
    ...:     for k, v in d.items():
    ...:         new_key = parent_key + sep + k if parent_key else k
    ...:         if isinstance(v, collections.MutableMapping):
    ...:             items.extend(flatten(v, new_key, sep=sep).items())
    ...:         else:
    ...:             items.append((new_key, v))
    ...:     return dict(items)
    ...: 

并生成扁平化的字典

In [25]: flat_expectededr = flatten(expectededr)

In [26]: flat_edr = flatten(edr)

现在简单比较一下:

In [27]: for key in flat_expectededr:
    ...:     if flat_edr.get(key) == flat_expectededr[key]:
    ...:         print "PASS"
    ...:     else:
    ...:         print "FAIL"
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS

简单的方法:

for i in edr.keys():
    if i in expectededr.keys():
        print 'true : key'+i
    else:
        print 'fail : key'+ i