python - 比较两个嵌套字典

标签 python python-2.7 amazon-web-services dictionary

我有两个嵌套字典,我想要比较字典 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/

相关文章:

python 如何将scrapy更新到0.22

ssl - AWS S3.NET 开发工具包

python - 使用cython性能下降

python - django-allauth:如何修改电子邮件确认网址?

python - 查找 pandas.Series 中的所有非数字元素

python - 自定义信号未传播

python - Windows 中的 Poetry 安装不起作用

python - 使属性方法可调用

Git push 什么都不推送

amazon-web-services - 使用 CloudFormation 为现有 EFS 创建 EFS 访问点