so i came up with a diff method to compare 2 dicts. i found it pretty
useful so i thought i'd share it with everyone. you can see the doctest
to check out suggested uses. since we can't modify built-ins, i
demonstrated adding a diff method to OrderedDict to show how one could
add it to your own mapping objects.
the core logic is compatible with python2 and 3 (i've only tested using
2.6.5 and 3.1.2). the doctest is suited for python3 though.
the interface is pretty straightforward. it would be awesome to have
this sucker as a method on the builtin dict, but that'd take a pep, no?
--
Jin Yi
__author__ = 'razamatan_retral_net_ignore_com'
from collections import Mapping
def diffdict(left, right):
''' returns the deep diff of two dicts. the return value the tuple
(left_diff, right_diff)
>>> diffdict(1, None)
(1, None)
>>> diffdict({1:2}, None)
({1: 2}, None)
>>> diffdict({1:2}, {3:4})
({1: 2, 3: <class 'KeyError'>}, {1: <class 'KeyError'>, 3: 4})
>>> from collections import OrderedDict
>>> x = OrderedDict({1:2, 3:{4:{5:[6,7], 8:9}}})
>>> diffdict(x, x)
(None, None)
>>> y = {1:2, 3:[4]}
>>> diffdict(x, y)
({3: {4: {8: 9, 5: [6, 7]}}}, {3: [4]})
>>> y = {1:2, 3:{4:{5:[6,7]}}}
>>> diffdict(x, y)
({3: {4: {8: 9}}}, {3: {4: {8: <class 'KeyError'>}}})
>>> y = {1:2, 3:{4:{5:{6:7}, 8:9}}}
>>> diffdict(x, y)
({3: {4: {5: [6, 7]}}}, {3: {4: {5: {6: 7}}}})
>>> del y[3]
>>> diffdict(x, y)
({3: {4: {8: 9, 5: [6, 7]}}}, {3: <class 'KeyError'>})
>>> y = {1:2, 3:{4:{5:[6,10], 8:9}}}
>>> diffdict(x, y)
({3: {4: {5: [6, 7]}}}, {3: {4: {5: [6, 10]}}})
>>> y = {1:100, 3:{4:{5:[6,7], 8:9}}}
>>> diffdict(x, y)
({1: 2}, {1: 100})
>>> diffdict(y, x)
({1: 100}, {1: 2})
>>> x.__class__.diff = diffdict
>>> x.__class__.__xor__ = diffdict
>>> x.diff(x)
(None, None)
>>> x ^ y
({1: 2}, {1: 100})
'''
# base case
if not isinstance(left, Mapping) or not isinstance(right, Mapping):
return (left, right)
# key exclusivity
left_diff = dict(i for i in left.items() if i[0] not in right)
right_diff = dict(i for i in right.items() if i[0] not in left)
right_diff.update((k, KeyError) for k in left_diff if k not in right_diff)
left_diff.update((k, KeyError) for k in right_diff if k not in left_diff)
# value differences
for k in (k for k in left if k in right):
if left[k] != right[k]:
(ld, rd) = diffdict(left[k], right[k])
left_diff[k] = ld or None
right_diff[k] = rd or None
left_diff = left_diff or None
right_diff = right_diff or None
return (left_diff, right_diff)
--
http://mail.python.org/mailman/listinfo/python-list