0

I have a program that compares two python dicts, and it works perfectly fine for non nested dictionaries with a depth of 1. The algorithm is pretty simple:

for key in dict1, if not in dict2
    print "-" key
for key in dict2, if not in dict1
    print "+" key
for dict2Value, if not equal to dict1Value
    print "+" dict2value
    print "-" dict1value

As I said it works fine with dicts that have a depth of 1, and are not nested. How should I change the algorithm to work with nested and dicts with greater depth, I have been stuck for a while.

my code:

def print_diff(dict1, dict2):
    for n in dict1:
        if n not in dict2:
            print('-   "' + str(n) + '":')
    for n in dict2:
        if n not in dict1:
            print('+   "' + str(n) + '":')
            continue
        if dict2[n] != dict1[n]:
            if type(dict2[n]) not in (dict, list):
                print('-   "' + str(n) + '" : "' + str(dict1[n]))
                print('+   "' + str(n) + '" : "' + str(dict2[n]))
            else:
                if type(dict2[n]) == dict:
                    print_diff(dict1[n], dict2[n])
                    continue
    return
larsks
  • 277,717
  • 41
  • 399
  • 399
user3230554
  • 81
  • 1
  • 8
  • What code have you tried? – Totem Feb 05 '14 at 01:55
  • What is the expected output for `dict1 = {'a': 3, 'b': {'b': 4, 'a': 5} }` and `dict2 = {'a': {'a': 3, 'b': 4}, 'a': 5}`? – Hyperboreus Feb 05 '14 at 02:23
  • @Totem added my code to the main post – user3230554 Feb 05 '14 at 03:41
  • 1
    Instead of obliterating your question, you might consider posting an answer yourself and then marked it as accepted when you're able. – larsks Feb 05 '14 at 05:39
  • -1 Please show an example usage of that function with the output you get and what would be your expected output. If that raises an error post the full-traceback. These are *essential* information for writing a good question. You should *never* use "does work" or "does not work" without further explanation. You should never say "it raises an error" without posting the *full*-traceback. – Bakuriu Feb 05 '14 at 09:14
  • If you want to do recursive diffs of included dicts then you need to state what the output format should be in that case. – Paddy3118 Feb 05 '14 at 20:40
  • You need to answer more of your open questions or people will ignore you. – Paddy3118 Feb 07 '14 at 19:53

2 Answers2

2

The following adopts a shorter form of outputting the differences (that you may change to follow your own).

Hierarchy is denoted by START/STOP in the output.

>>> def dictdiff(d1, d2):
    s1, s2 = set(d1), set(d2)
    in1, in12, in2 = s1 - s2, s1 & s2, s2 - s1
    if in1:  print('Keys only in 1:', sorted(in1))
    if in2:  print('Keys only in 2:', sorted(in2))
    sameval = {key for key in in12 if d1[key] == d2[key]}
    if sameval: print('Keys with equal values:', sorted(sameval))
    diffval = in12 - sameval
    diffdict = {key for key in diffval if type(d1[key]) == type(d2[key]) == dict}
    diffother = diffval - diffdict
    if diffother: print('Keys with different values (that are not both dicts):', sorted(diffother))
    for key in sorted(diffdict):
        print('## START dictdiff for common key', key)
        dictdiff(d1[key], d2[key])
        print('## STOP  dictdiff for common key', key)


>>> d1 = dict(a=1, b=2, c=dict(x=1, y=2), d=1, f=dict(s=1, t=3))
>>> d2 = dict(a=1, b=3, c=dict(x=1, y=2), e=1, f=dict(s=1, t=2))
>>> dictdiff(d1, d2)
Keys only in 1: ['d']
Keys only in 2: ['e']
Keys with equal values: ['a', 'c']
Keys with different values (that are not both dicts): ['b']
## START dictdiff for common key f
Keys with equal values: ['s']
Keys with different values (that are not both dicts): ['t']
## STOP  dictdiff for common key f
>>> 

It might be good to remember the following too:

>>> d1['c'] is d2['c']
False
>>> d1['c'] == d2['c']
True
>>> 
Paddy3118
  • 4,704
  • 27
  • 38
0

comparing 2 dictionaries using recursion:

d1= {'a':{'b':{'cs':10},'d':{'cs':20}}}
d2= {'a':{'b':{'cs':30} ,'d':{'cs':20}},'newa':{'q':{'cs':50}}}

def findDiff(d1, d2, path=""):
    for k in d1.keys():
        if not d2.has_key(k):
            print path, ":"
            print "keys not in d2: " + k, "\n"
        else:
            if type(d1[k]) is dict:
                if path == "":
                    path = k
                else:
                    path = path + "->" + k
                findDiff(d1[k],d2[k], path)
            else:
                if d1[k] != d2[k]:
                    print path, ":"
                    print " - ", k," : ", d1[k]
                    print " + ", k," : ", d2[k] 

print "comparing d1 to d2:"
print findDiff(d1,d2)
print "comparing d2 to d1:"
print findDiff(d2,d1)

Output:

comparing d1 to d2:
a->b :
 -  cs  :  10
 +  cs  :  30
None
comparing d2 to d1:
a->b :
 -  cs  :  30
 +  cs  :  10
a :
keys not in d2: newa

None
Pavan Gupta
  • 17,663
  • 4
  • 22
  • 29