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

Reply via email to