Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@neilalexander
Last active July 13, 2017 07:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neilalexander/f2f00016eb001da8e5e364b809a58635 to your computer and use it in GitHub Desktop.
Save neilalexander/f2f00016eb001da8e5e364b809a58635 to your computer and use it in GitHub Desktop.
Python 3 functions for comparing complex dict structures for additions, changes and deletions, and for walking the tree and running a given function on nodes.
class DeltaDict:
#
# changes(dict1, dict2) returns dict
#
# Finds nodes that appear in both dict1 and dict2 but
# where the values have changed
#
def changes(d1, d2):
d = dict()
s = set(d1.keys()).intersection(set(d2.keys()))
try:
for k in { o : d2[o] for o in s if d1[o] != d2[o] }:
a = DeltaDict.changes(d1[k], d2[k])
if a != {}:
d[k] = a
except:
d[k] = d2[k]
return d
#
# additions(dict1, dict2) returns dict
#
# Finds nodes that appear in dict2 but not in dict1
#
def additions(d1, d2):
d = dict()
for k, v in d2.items():
try: d1[k]
except:
if type(v) is not dict: d[k] = v
if type(v) is dict:
try: a = DeltaDict.additions(d1[k], d2[k])
except KeyError: a = DeltaDict.additions({}, d2[k])
if a != {}:
d[k] = a
return d
#
# deletions(dict1, dict2) returns dict
#
# Finds nodes that appear in dict1 but not in dict2
#
def deletions(d1, d2):
d = dict()
for k, v in d1.items():
try:
if d2[k] and type(v) is dict:
try: a = DeltaDict.deletions(d1[k], d2[k])
except KeyError: a = DeltaDict.deletions(d1[k], {})
if a != {}:
d[k] = a
except:
if v != {}:
d[k] = v
return d
#
# walkall(dict, function) yields path, returnval
#
# Walks all nodes of the given dict structure, including
# inner nodes
#
def walkall(d, f, p = []):
for k, v in d.items():
p.append(k)
if type(v) is dict:
yield from DeltaDict.walkall(v, f, p)
yield p, f(v)
p.pop()
#
# walkleaf(dict, function) yields path, returnval
#
# Walks only leaf nodes of the given dict structure, not
# including inner nodes
#
def walkleaf(d, f, p = []):
for k, v in d.items():
p.append(k);
if type(v) is dict:
yield from DeltaDict.walkleaf(v, f, p)
else:
yield p, f(v)
p.pop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment