【问题标题】:Comparing two nested dictionary比较两个嵌套字典
【发布时间】:2017-07-14 11:37:10
【问题描述】:

我有两个要比较的嵌套字典 字典 d1 具有我从 yaml 文件中提取的所需值,d2 具有我从 aws 安全组获取的当前值。我想比较两个dict并显示

场景 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

但是当我有两个 dict 时无法检查场景 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'}]}]}

输出:

【问题讨论】:

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


    【解决方案1】:

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

    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!
    

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

    【讨论】:

    • 非常感谢您的帮助。该代码确实适用于场景 2,但我检查了几个案例,例如场景 3(已更新),它未能检测到 cidrIp 值的变化,因为它在 D2 中是“0.0.0.0/0”,而在“0.0.0.0/1”中是“0.0.0.0/1”在 D1。我认为这是因为我们正在检查长度而不是值本身?你能帮忙吗
    • @AjayMisra 不,这种情况下的问题是类型。在比较两个值之前,我正在检查 if type(d1[key]) == type(d2[key]): 在您更新的问题中,d1 的 CidrIp 是 unicode 类型(这是字符串前面的 u),而 d2 的 CidrIp 是常规的 str 类型.我不知道是什么导致了您这边的这种差异。是否要保持这种状态取决于您。或者,如果您确定数据中没有特殊的 Unicode 字符,您可以使用 str 函数将所有 Unicode 字符串转换为常规字符串。
    • 非常感谢您的帮助。你太棒了。在接下来的几周里,我将在 python 上做更多的工作,希望能在 Stackoverflow 上看到你更多:)
    猜你喜欢
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 2018-09-19
    相关资源
    最近更新 更多