Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python dict update diff

Does python have any sort of built in functionality of notifying what dictionary elements changed upon dict update? For example I am looking for some functionality like this:

>>> a = {'a':'hamburger', 'b':'fries', 'c':'coke'}
>>> b = {'b':'fries', 'c':'pepsi', 'd':'ice cream'}
>>> a.diff(b)
{'c':'pepsi', 'd':'ice cream'}
>>> a.update(b)
>>> a
{'a':'hamburger', 'b':'fries', 'c':'pepsi', 'd':'ice cream'}

I am looking to get a dictionary of the changed values as shown in the result of a.diff(b)

like image 650
adam Avatar asked Apr 03 '09 19:04

adam


3 Answers

No, but you can subclass dict to provide notification on change.

class ObservableDict( dict ):
    def __init__( self, *args, **kw ):
        self.observers= []
        super( ObservableDict, self ).__init__( *args, **kw )
    def observe( self, observer ):
        self.observers.append( observer )
    def __setitem__( self, key, value ):
        for o in self.observers:
            o.notify( self, key, self[key], value )
        super( ObservableDict, self ).__setitem__( key, value )
    def update( self, anotherDict ):
        for k in anotherDict:
            self[k]= anotherDict[k]

class Watcher( object ):
    def notify( self, observable, key, old, new ):
        print "Change to ", observable, "at", key

w= Watcher()
a= ObservableDict( {'a':'hamburger', 'b':'fries', 'c':'coke'} )
a.observe( w )
b = {'b':'fries', 'c':'pepsi'}
a.update( b )

Note that the superclass Watcher defined here doesn't check to see if there was a "real" change or not; it simply notes that there was a change.

like image 139
S.Lott Avatar answered Oct 05 '22 16:10

S.Lott


one year later

I like the following solution:

>>> def dictdiff(d1, d2):                                              
        return dict(set(d2.iteritems()) - set(d1.iteritems()))
... 
>>> a = {'a':'hamburger', 'b':'fries', 'c':'coke'}
>>> b = {'b':'fries', 'c':'pepsi', 'd':'ice cream'}
>>> dictdiff(a, b)
{'c': 'pepsi', 'd': 'ice cream'}
like image 25
remosu Avatar answered Oct 05 '22 17:10

remosu


No, it doesn't. But it's not hard to write a dictionary diff function:

def diff(a, b):
  diff = {}
  for key in b.keys():
    if (not a.has_key(key)) or (a.has_key(key) and a[key] != b[key]):
      diff[key] = b[key]
  return diff
like image 29
Can Berk Güder Avatar answered Oct 05 '22 17:10

Can Berk Güder