-1

I am trying to recursively compare below two python dictionaries:

expectededr = {'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'attempted': {'smpp': {'registeredDelivery': 0}, 'status': 'success', 'OATON': 1, 'OANPI': 1, 'DATON': 1, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404'}, 'customerID': 'customer01', 'productID': 'product'}

edr = {'Category': 'NO', 'Type': 'mt', 'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'protocolID': 'smpp', 'direction': 'attempted', 'attempted': {'status': 'success', 'OANPI': 1, 'DATON': 1, 't2': 1512549691602, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404', 'smpp': {'fragmented': False, 'sequenceID': 1, 'registeredDelivery': 0, 'messageID': '4e7b48ad-b39e-4e91-a7bb-2de463e4a6ee', 'srcPort': 39417, 'messageType': 4, 'Status': 0, 'ESMClass': 0, 'dstPort': 0, 'size': 0}, 'OATON': 1, 'PID': 0, 't1': 1512549691602}, 'customerID': 'customer01', 'productID': 'product'}  

I am trying to compare the in a way that find and compare the key and value of first dictionary in second and if matching then print PASS else print FAIL.

for key in expectededr:
   if expectededr[key] == edr[key]:
       print("PASS")
   else:
       print("FAIL")

Output:

FAIL
PASS
PASS
PASS

Above code is not able to compare all the keys and values as these are nested dictionaries.
As you can see below, if i print key and values above i see that its not going in sub dictionary and missing their keys:

for key in expectededr:
    if expectededr[key] == edr[key]:
        print(expectededr[key])
        print(edr[key])

Output:

customer01
customer01
e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3
e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3
product
product

Could someone help to update this code so that I can do the comparision in these nested dictionaries ?

Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
Ujjawal Khare
  • 756
  • 2
  • 7
  • 20

2 Answers2

1

One way is to flatten the dictionaries and then compare if the keys match.

So Lets initialiaze your dicts first:

In [23]: expectededr = {'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'attempted': {'smpp': {'registeredDelivery': 0}, 'status': 'success', 'OATON': 1, 'OANP
    ...: I': 1, 'DATON': 1, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404'}, 'customerID': 'customer01', 'productID': 'product'}
    ...: 
    ...: edr = {'Category': 'NO', 'Type': 'mt', 'uid': 'e579b8cb-7d9f-4c0b-97de-a03bb52a1ec3', 'protocolID': 'smpp', 'direction': 'attempted', 'attempted': {'
    ...: status': 'success', 'OANPI': 1, 'DATON': 1, 't2': 1512549691602, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404', 'smpp': {'fragmented': False, '
    ...: sequenceID': 1, 'registeredDelivery': 0, 'messageID': '4e7b48ad-b39e-4e91-a7bb-2de463e4a6ee', 'srcPort': 39417, 'messageType': 4, 'Status': 0, 'ESMCl
    ...: ass': 0, 'dstPort': 0, 'size': 0}, 'OATON': 1, 'PID': 0, 't1': 1512549691602}, 'customerID': 'customer01', 'productID': 'product'}  
    ...: 

For flattening your dictionaries, we can use the approach suggested in Flatten nested Python dictionaries, compressing keys:

In [24]: import collections
    ...: 
    ...: def flatten(d, parent_key='', sep='_'):
    ...:     items = []
    ...:     for k, v in d.items():
    ...:         new_key = parent_key + sep + k if parent_key else k
    ...:         if isinstance(v, collections.MutableMapping):
    ...:             items.extend(flatten(v, new_key, sep=sep).items())
    ...:         else:
    ...:             items.append((new_key, v))
    ...:     return dict(items)
    ...: 

And generated flattened dicts

In [25]: flat_expectededr = flatten(expectededr)

In [26]: flat_edr = flatten(edr)

Now its a simple comparison:

In [27]: for key in flat_expectededr:
    ...:     if flat_edr.get(key) == flat_expectededr[key]:
    ...:         print "PASS"
    ...:     else:
    ...:         print "FAIL"
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
  • using this its not comparing 'status': 'success' which is inside 'attempted': {'smpp': {'registeredDelivery': 0}, 'status': 'success', 'OATON': 1, 'OANP ...: I': 1, 'DATON': 1, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404'}, – Ujjawal Khare Dec 06 '17 at 12:50
  • 1
    @UjjawalKhare I see. Is it guaranteed that the same key is present only once within any level of the nesting? If that is the case, in function flatten above, you can replace `new_key = parent_key + sep + k if parent_key else k ` with `new_key = k` and things will work smoothly. If however, keys can be repeated, then you simply can't compare in an automated fashion, since one key could tell you it matches while other one may not match. FWIW, there are 2 status and Status keys already within the dictionary. – Anshul Goyal Dec 06 '17 at 13:01
  • I tried your suggestion and this is exactly how I wanted it to work. Only one thing I want to know ... is there any way to print that its printing FAIL for which element ? can we limit the so many occurrences of PASS and FAIL and limit it like even if one key value matching failed then we just print non matching key and value and print FAIL ? – Ujjawal Khare Dec 06 '17 at 13:23
  • @UjjawalKhare You can use a `break` statement in the else section, or can even print the key along side pass or fail. If you've further doubts, ask a new question. – Anshul Goyal Dec 06 '17 at 15:41
0

Simple way :

for i in edr.keys():
    if i in expectededr.keys():
        print 'true : key'+i
    else:
        print 'fail : key'+ i
Bhanuchander Udhayakumar
  • 1,581
  • 1
  • 12
  • 30
  • Its still not checking and comparing kyes of the sub dictionary {'smpp': {'registeredDelivery': 0}, 'status': 'succes', 'OATON': 1, 'OANPI': 1, 'DATON': 1, 'DANPI': 1, 'OA': '12149921220', 'DA': '1514525404'} for example both dictionaries have 'status':'success' but its not comparing this key value using above code. – Ujjawal Khare Dec 06 '17 at 11:41
  • @UjjawalKhare Check my answer, let me know if that works for you. – Anshul Goyal Dec 06 '17 at 11:53
  • @mu: please check my comment – Ujjawal Khare Dec 06 '17 at 12:50