Diff two dictionaries returning just the differences. If an item is not found, it is represented by the string "<KEYNOTFOUND>". If there is a better way, please share. :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | KEYNOTFOUND = '<KEYNOTFOUND>' # KeyNotFound for dictDiff
def dict_diff(first, second):
""" Return a dict of keys that differ with another config object. If a value is
not found in one fo the configs, it will be represented by KEYNOTFOUND.
@param first: Fist dictionary to diff.
@param second: Second dicationary to diff.
@return diff: Dict of Key => (first.val, second.val)
"""
diff = {}
# Check all keys in first dict
for key in first.keys():
if (not second.has_key(key)):
diff[key] = (first[key], KEYNOTFOUND)
elif (first[key] != second[key]):
diff[key] = (first[key], second[key])
# Check all keys in second dict to find missing
for key in second.keys():
if (not first.has_key(key)):
diff[key] = (KEYNOTFOUND, second[key])
return diff
|
Try using set.symmetric_difference():
Since dictionaries also have values you'd also have to prove that these are equal for the intersection of the sets of dictionary keys. If the value associated with the particular key in a "config object" has a known value then sets, not dictionaries, were probably a better data structure in the first place.
Good comments, thanks guys. :)
I did not think of this myself but definately wanted to share:
diff=dict()
for key in first.keys()+second.keys(): try : x = first[key] except KeyError: diff[key] = (None,second[key]) try : x = second[key] except KeyError: diff[key] = (first[key],None)
print diff
A little more verbose version.
Here's my code for this:
Not quite the same interface for output, but the algorithm is pretty clean.
Here's one that returns any key that's only in one of the dicts and any value that differs in the two dicts (returns the one in the second dict - just change the order or the .get()s to change behaviour).
Short version:
Or as a function (same code, but easier to read):
This uses dictionary comprehensions, and allows you to change the KEYNOTFOUND string if desired.
Hi, this is working for me:
def dict_diff(d1, d2, NO_KEY='<KEYNOTFOUND>'): set_d1 = set(d1.keys()) set_d2 = set(d2.keys()) both = set_d1 & set_d2 diff = {k:(d1[k], d2[k]) for k in both if d1[k] != d2[k]} diff.update({k:(d1[k], NO_KEY) for k in set_d1 - both}) diff.update({k:(NO_KEY, d2[k]) for k in set_d2 - both}) return diff
def dict_diff(d1, d2, NO_KEY='<KEYNOTFOUND>'): set_d1 = set(d1.keys()) set_d2 = set(d2.keys()) both = set_d1 & set_d2 diff = {k:(d1[k], d2[k]) for k in both if d1[k] != d2[k]} diff.update({k:(d1[k], NO_KEY) for k in set_d1 - both}) diff.update({k:(NO_KEY, d2[k]) for k in set_d2 - both}) return diff