Is there a pythonic way to update a dictionary value when the update depends on the value itself?

I find myself in many situations where I have a dictionary value that I want to update with a new value, but only if the new value meets some criteria regarding the current value (for example, more).

I am currently writing expressions similar to:

dictionary[key] = max(newvalue, dictionary[key])

which works fine, but I keep thinking that there may be a more neat way to do this, which does not require repetition.

Thanks for any suggestions.

+3
source share
4 answers

Just write yourself a helper function:

def update(dictionary, key, newvalue, func=max):
    dictionary[key] = func(dictionary[key], newvalue)
+1
source

, . __setitem__. , , , , , , . , , .

+3

Not sure if it's neat, but one way to avoid repetition is to use the object-oriented approach and a subclass of the built-in class dictto do something capable of doing what you want. This also has the advantage that instances of your custom class can be used instead of instances dictwithout changing the rest of your code.

class CmpValDict(dict):
    """ dict subclass that stores values associated with each key based
       on the return value of a function which allow the value passed to be
       first compared to any already there (if there is no pre-existing
       value, the second argument passed to the function will be None)
    """
    def __init__(self, cmp=None, *args, **kwargs):
        self.cmp = cmp if cmp else lambda nv,cv: nv  # default returns new value
        super(CmpValDict, self).__init__(*args, **kwargs)

    def __setitem__(self, key, value):
        super(CmpValDict, self).__setitem__(key, self.cmp(value, self.get(key)))

cvdict = CmpValDict(cmp=max)

cvdict['a'] = 43
cvdict['a'] = 17
print cvdict['a']  # 43

cvdict[43] = 'George Bush'
cvdict[43] = 'Al Gore'
print cvdict[43]  # George Bush
+1
source

How about using the Python version of the ternary operator:

d[key]=newval if newval>d[key] else d[key]

or one line if:

if newval>d[key]: d[key]=newval
0
source

All Articles