So I have a python dictionary, call it d1
, and a version of that dictionary at a later point in time, call it d2
. I want to find all the changes between d1
and d2
. In other words, everything that was added, removed or changed. The tricky bit is that the values can be ints, strings, lists, or dicts, so it needs to be recursive. This is what I have so far:
def dd(d1, d2, ctx=""): print "Changes in " + ctx for k in d1: if k not in d2: print k + " removed from d2" for k in d2: if k not in d1: print k + " added in d2" continue if d2[k] != d1[k]: if type(d2[k]) not in (dict, list): print k + " changed in d2 to " + str(d2[k]) else: if type(d1[k]) != type(d2[k]): print k + " changed to " + str(d2[k]) continue else: if type(d2[k]) == dict: dd(d1[k], d2[k], k) continue print "Done with changes in " + ctx return
It works just fine unless the value is a list. I cant quite come up with an elegant way to deal with lists, without having a huge, slightly changed version of this function repeated after a if(type(d2) == list)
.
Any thoughts?
EDIT: This differs from this post because the keys can change
Advertisement
Answer
One option would be to convert any lists you run into as dictionaries with the index as a key. For example:
# add this function to the same module def list_to_dict(l): return dict(zip(map(str, range(len(l))), l))
# add this code under the 'if type(d2[k]) == dict' block elif type(d2[k]) == list: dd(list_to_dict(d1[k]), list_to_dict(d2[k]), k)
Here is the output with the sample dictionaries you gave in comments:
>>> d1 = {"name":"Joe", "Pets":[{"name":"spot", "species":"dog"}]} >>> d2 = {"name":"Joe", "Pets":[{"name":"spot", "species":"cat"}]} >>> dd(d1, d2, "base") Changes in base Changes in Pets Changes in 0 species changed in d2 to cat Done with changes in 0 Done with changes in Pets Done with changes in base
Note that this will compare index by index, so it will need some modification to work well for list items being added or removed.