Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard class for an infinitely nested defaultdict?

Does anyone know if there's a standard class for an infinitely nestable dictionary in Python?

I'm finding myself repeating this pattern:

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
d['abc']['def']['xyz'] += 1

If I want to add "another layer" (e.g. d['abc']['def']['xyz']['wrt']), I have to define another nesting of defaultdicts.

To generalize this pattern, I've written a simple class that overrides __getitem__ to automatically create the next nested dictionary.

e.g.

d = InfiniteDict(('count',0),('total',0))
d['abc']['def']['xyz'].count += 0.24
d['abc']['def']['xyz'].total += 1
d['abc']['def']['xyz']['wrt'].count += 0.143
d['abc']['def']['xyz']['wrt'].total += 1

However, does anyone know of a pre-existing implementation of this idea? I've tried Googling, but I'm not sure what this would be called.

like image 250
Cerin Avatar asked Nov 14 '10 15:11

Cerin


People also ask

Can you nest Defaultdict?

Now that we understand nested dictionaries and defaultdicts , we can get into nested defaultdicts . This is concept is extremely powerful as it allows you to build complex dictionaries with a simple initialization. The only caveat is that you need to know the depth of your data structure in advance.

What is the default value in Defaultdict?

The default value there is not 1, it's 0.

Can you have a Defaultdict in a Defaultdict?

@Jonathan: Yes sure, the argument of a defaultdict (in this case is lambda : defaultdict(int) ) will be called when you try to access a key that don't exist and the return value of it will be set as the new value of this key which mean in our case the value of d[Key_dont_exist] will be defaultdict(int) , and if you try ...

How does Defaultdict work Defaultdict will automatically?

The Python defaultdict type behaves almost exactly like a regular Python dictionary, but if you try to access or modify a missing key, then defaultdict will automatically create the key and generate a default value for it. This makes defaultdict a valuable option for handling missing keys in dictionaries.


2 Answers

I think this one-liner is a nearly perfect solution:

>>> from collections import defaultdict
>>> infinite_defaultdict = lambda: defaultdict(infinite_defaultdict)
>>> d = infinite_defaultdict() 
>>> d['x']['y']['z'] = 10

by Raymond Hettinger on Twitter (https://twitter.com/raymondh/status/343823801278140417)

like image 175
michaelkrisper Avatar answered Sep 30 '22 10:09

michaelkrisper


This lends itself naturally to a recursive definition.

>>> import collections
>>> def nested_dd():
...     return collections.defaultdict(nested_dd)
...
>>> foo = nested_dd()
>>> foo
defaultdict(<function nested_dd at 0x023F0E30>, {})
>>> foo[1][2]=3
>>> foo[1]
defaultdict(<function nested_dd at 0x023F0E30>, {2: 3})
>>> foo[1][2]
3
like image 36
Katriel Avatar answered Sep 30 '22 12:09

Katriel