Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value of largest key if key not found in defaultdict

Requirement

I would like to define a defaultdict that returns the value of the largest key, if the key that I am providing is not in the dictionary. Basically I am looking for a way to store config information with the twist, that values default to their last defined values.

Solution so far

My implementation is as follows:

from collections import defaultdict

d = defaultdict(lambda: d[max(d.keys())])
d.update({2010: 10, 2011: 20, 2013: 30 })

for year in [2010, 2011, 2013, 2014]:
    print(f"{year}: {d[year]}")

which correctly produces:

2010: 10
2011: 20
2013: 30
2014: 30

(a more elaborate version could also return values for keys smaller than the smallest).

Question

Is there a more elegant way to define the lambda function without the requirement that you know the dictionary's name?

like image 320
divingTobi Avatar asked Nov 24 '25 07:11

divingTobi


1 Answers

Calculating frequently the max key looks quite inefficient because in Python keys are in hash maps so they aren't sorted.

Consider writing your own default_dict:

class DictLast(collections.MutableMapping,dict):
    def __init__(self, *args, **kwargs):
        self.theMaxKey = None 
        self.update(*args, **kwargs)
    def __getitem__(self, key):
        if dict.__contains__(self,key): 
            return dict.__getitem__(self,key)
        return dict.__getitem__(self, self.theMaxKey)
    def __setitem__(self, key, value):
        if self.theMaxKey is None:
            self.theMaxKey = key
        if key > self.theMaxKey: 
            self.theMaxKey = key
        dict.__setitem__(self,key,value)   

d = DictLast()
d.update({2010: 10, 2011: 20, 2013: 30 })

for year in [2010, 2011, 2013, 2014]:
    print(f"{year}: {d[year]}")

please notice that, whenever asked for a missing key, my implementation doesn't add the key to the dictionary. I assume this is the intended behavior

If you are in doubt, try this code with my and your implementation:

for year in [2010, 2011, 2013, 2015]:
    print(f"{year}: {d[year]}")
d[2014]=7
for year in [2010, 2011, 2013, 2015]:
    print(f"{year}: {d[year]}")

to understand what's the difference

EDIT: As pointed out in the comments below:

"this strategy only works if you don't remove items from the dictionary".

IMO If you want the data structure to be well designed you should manage removal too (up to you to decide if you want to raise, recalculate the max or do something different).

like image 95
jimifiki Avatar answered Nov 26 '25 20:11

jimifiki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!