我有两个嵌套字典,我想要比较字典 d1 具有我从 yaml 文件中提取的所需值,而 d2 具有我从 aws 安全组获取的当前值。我想比较两个字典并显示
场景1 d2 中存在但 d1 中不存在的意外值
场景2 并显示 d1 中存在但 d2 中不存在的值。
我现在有以下代码
def CompareDict(d1, d2, ctx=""):
for k in d2:
if k not in d1:
continue
if d2[k] != d1[k]:
if type(d2[k]) not in (dict, list):
print k +" Expected Value "+str(d1[k])+" but found "+str(d2[k])
else:
if type(d1[k]) != type(d2[k]):
continue
else:
if type(d2[k]) == dict:
CompareDict(d1[k], d2[k], k)
continue
elif type(d2[k]) == list:
CompareDict(list_to_dict(d1[k]), list_to_dict(d2[k]), k)
return
当我的两个字典是 - 时,这对于以下情况效果很好 -
D2
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 99, u'FromPort': 0, u'IpRanges': [{u'CidrIp': '104.129.192.69/32'}], u'IpProtocol': 'udp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [], u'IpProtocol': 'tcp'}]}]}
D1
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': u'0.0.0.0/1'}], u'IpProtocol': u'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': u'0.0.0.0/32'}], u'IpProtocol': u'tcp'}]}]}
输出
ToPort Expected Value 89 but found 99
FromPort Expected Value 80 but found 0
CidrIp Expected Value 0.0.0.0/1 but found 104.129.192.69/32
IpProtocol Expected Value tcp but found udp
但是当我有两个字典时无法检查场景 2
--D2----
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [], u'IpProtocol': 'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [], u'IpProtocol': 'tcp'}]}]}
——D1——
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': u'0.0.0.0/1'}], u'IpProtocol': u'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': u'0.0.0.0/0'}], u'IpProtocol': u'tcp'}]}]}
输出
None
有人可以帮忙吗?我是 python 新手,非常感谢任何帮助
更新 -
场景 3(无法检测 cidrIp 值的变化,因为 D2 中为“0.0.0.0/0”,D1 中为“0.0.0.0/1”。)
D2
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': '0.0.0.0/0'}], u'IpProtocol': 'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': '0.0.0.0/32'}], u'IpProtocol': 'tcp'}]}]}
D1
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': u'0.0.0.0/1'}], u'IpProtocol': u'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': u'0.0.0.0/32'}], u'IpProtocol': u'tcp'}]}]}
Output :
最佳答案
我想这会满足你所需要的一切。
import json
def compareIterables(d1, d2):
if [type(d1), type(d2)] == [dict,dict]:
notInD2 = set(d1.keys()) - set(d2.keys())
notInD1 = set(d2.keys()) - set(d1.keys())
inBoth = set(d2.keys()) & set(d1.keys())
for key in notInD2:
print "D2[{}] is not defined. Value in D1: {}".format(key, json,dumps(D1[key]))
for key in notInD1:
print "D1[{}] is not defined. Value in D2: {}".format(key, json,dumps(D2[key]))
elif [type(d1), type(d2)] == [list,list]:
len1 = len(d1)
len2 = len(d2)
if(len(d1) != len(d2)):
print "lists {} and {} do not have the same length!".format(d1,d2)
return
else:
inBoth = range(0,len1)
for key in inBoth:
if all([x not in [dict,list] for x in [type(d1[key]),type(d2[key])]]):
if type(d1[key]) == type(d2[key]):
if d1[key] != d2[key]:
print "d1[{0}] ({1}) does not match d2[{0}] ({2})".format(key, d1[key], d2[key])
else:
if([type(d1[key]),type(d2[key])] == [list,list]):
compareIterables(d1[key],d2[key])
elif([type(d1[key]),type(d2[key])] == [dict,dict]):
compareIterables(d1[key],d2[key])
elif type(d1[key]) != type(d2[key]):
print "type of d1[{0}] ({1}) does not match d2[{0}] ({2})".format(key, type(d1[key]), type(d2[key]))
这会输出您提供的第二对字典。
lists [{u'CidrIp': u'0.0.0.0/1'}] and [] do not have the same length!
lists [{u'CidrIp': u'0.0.0.0/0'}] and [] do not have the same length!
您可以修改此脚本以递归地传递 key ,以便更好地识别或您需要的任何其他功能。这只是一个基准。
关于python - 比较两个嵌套字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45092820/