比较两个嵌套字典

时间:2017-07-14 00:27:27

标签: 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预期值89但发现99

     

FromPort预期值80但找到0

     

CidrIp预期值0.0.0.0/1但发现104.129.192.69/32

     

IpProtocol期望值tcp但找到了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'}]}]}

输出

  

请有人帮忙。我是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'}]}]}
  

输出:

1 个答案:

答案 0 :(得分:0)

我认为这将满足您的一切需求。

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!

您可以修改此脚本以递归方式传递密钥,以便更好地识别或使用您需要的任何其他功能。这只是一个基线。