2017-07-14 21 views
1

私は辞書d1が私のyamlファイルから引っ張っている希望の値を持っていると私は比較したい2つの入れ子の辞書があり、d2はawsのセキュリティグループから取得している現在の値を持っています。私は2つの辞書を比較するとd2ではなく2つのネストされた辞書を比較する

D1にシナリオ2 ともD1にありますが、D2にはなかった値を表示がある

シナリオ1つの 予期しない値を表示したいです。

が、私は今のように次のコードを持っている

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 

これは私の2つの辞書があり、以下のシナリオで正常に動作します -

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'}]}]} 

Outp UT

ToPort期待値89が、99

FROMPORTを見つけましたが値80期待が、0

CidrIp期待値0.0.0.0/1が見つかりましたが104.129.192.69/32

IPプロトコル期待を見つけましたバリューTCPしかし

UDP見つけしかし、私は

ように2つの辞書を持っている場合、シナリオ2のチェックに失敗しました----

{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

--D2 ---

{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に新しいですが

が更新任意の助けを本当に感謝 - それはD2で「0.0.0.0/0」ですと「0.0.0.0/1」として

シナリオ3(cidrIp値の変化を検出することができませんD1である。)

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'}]}]} 

出力:

答えて

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])) 

これは、指定した2番目の辞書のペアを出力します。

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! 

このスクリプトを修正することで、より正確な識別や必要な機能を再帰的に渡すことができます。これは単なるベースラインです。

+0

ありがとうございました。コードはシナリオ2で動作しますが、シナリオ3(問題の更新)のようなケースの場合は、D2と0.0.0.0/1の '0.0.0.0/0'のようにcidrIp値の変更を検出できませんでしたD1で。値そのものではなく長さをチェックしているからだと思いますか?助けてもらえますか? –

+0

@AjayMisraいいえ、この場合の問題はタイプです。 2つの値を比較する前に、 'type(d1 [key])== type(d2 [key]):'をチェックしています。更新された質問では、d1の 'CidrIp'は' unicode'型( 'u' infront d2の 'CidrIp'は通常の' str'型です。私はあなたの側でこの違いを引き起こしているのか分かりません。あなたがその状態を保つかどうかは、あなた次第です。また、データに特別なUnicode文字がないことが確かな場合は、 'str'関数を使用して、すべてのUnicode文字列を通常の文字列にキャストすることもできます。 –

+0

ありがとう、本当に助けてくれました。あなたは素晴らしいです。私は今後数週間Pythonでもっと努力していきたいと思っています。 –

関連する問題