Python Forum
Dynamic Allocation of Nested Dictionaries
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dynamic Allocation of Nested Dictionaries
#11
Still think the exec is ugly and bad.

I think this is pretty clean way to set from a list:
from collections import defaultdict
 

def DynamicNestedDict():
    return defaultdict(DynamicNestedDict)


def try_dynamic_nested_dict():
    keylist = ['bind', 'application level', 'binding']
    loc = [20, 96, 100, 101, 102, 104, 105, 115, 193, 434, 546]
 
    dd = DynamicNestedDict()

    level = dd
    for key in keylist[:-1]:
        level = level[key]
    level[keylist[-1]] = loc
 
    print("dd['bind']['application level']['binding']: {}"
          .format(dd['bind']['application level']['binding']))
 
 
if __name__ == '__main__':
    try_dynamic_nested_dict()
Edit:
And for a possibly more convenient API:
from collections import defaultdict

 
class DynamicNestedDict(defaultdict):
    def __init__(self, *args, **kwargs):
        super(DynamicNestedDict, self).__init__(DynamicNestedDict, *args, **kwargs)

    def set_from_list(self, keylist, value):
        level = self
        for key in keylist[:-1]:
            level = level[key]
        level[keylist[-1]] = value

    def get_from_list(self, keylist):
        level = self
        for key in keylist[:-1]:
            level = level[key]
        return level[keylist[-1]]


def try_dynamic_nested_dict():
    keylist = ['bind', 'application level', 'binding']
    loc = [20, 96, 100, 101, 102, 104, 105, 115, 193, 434, 546]
    dd = DynamicNestedDict()
    dd.set_from_list(keylist, loc)
    result = dd.get_from_list(keylist)
    print("dd['bind']['application level']['binding']: {}".format(result))


if __name__ == '__main__':
    try_dynamic_nested_dict()
Testing certainly needed.
#12
Merkire,

The first post to this thread used a class for the dynamic recursion.
The direct overload is cleaner.

I do like the removal of exec, with your loop.
So will keep these

I don't want to reject Micseydel's lambda suggestion until I (or someone else) has
a chance to time them with more data.
#13
There is a nested dict on pypi that might be of interest.
#14
Quote:I don't want to reject Micseydel's lambda suggestion until I (or someone else) has a chance to time them with more data.
As far as I can tell one of the lambdas in Mic's version is unnecessary, as shown:
def DynamicNestedDict():
    return defaultdict(DynamicNestedDict)
Or use a lambda if you really prefer (though it is less idiomatic imo)
DynamicNestedDict = lambda : defaultdict(DynamicNestedDict)
Correct me if you believe this does something different than the one with two lambdas that Mic proposed.

The reason to turn it back into a class is to write those list setters and getters as proper methods so a user doesn't need to think about them.  It is about an intuitive API; not code minimization. Also, unlike your initial version my class version is a subclass of defaultdict. You don't need to create an instance and then call a method to create the dict; it happens in the init automatically.

Quote:until I (or someone else) has a chance to time them with more data.
Also want to point out that the reason to use a true function, lambda, or class has nothing to do with code speed here.
#15
I didn't mean to advocate the lambda over a named function, and I actually prefer the function version, I just Google'd for nested defaultdict and (after a bit of testing) pasted the most straightforward thing. And I wouldn't worry about code speed until the cleanest code turns out to be a bottleneck.
#16
Ok,

I tested (enough for current needs) this version, and will  be importing it into the project
where I decided I needed it, and if necessary, fix any new bugs that pop up and re-post.

Thanks all for contributions and suggestions.

from collections import defaultdict


class DynamicNestedDict(defaultdict):
    def __init__(self, *args, **kwargs):
        super(DynamicNestedDict, self).__init__(DynamicNestedDict, *args, **kwargs)

    def set_from_list(self, keylist, value):
        level = self
        for key in keylist[:-1]:
            level = level[key]
        level[keylist[-1]] = value

    def get_from_list(self, keylist):
        level = self
        for key in keylist[:-1]:
            level = level[key]
        return level[keylist[-1]]


def try_dynamic_nested_dict():
    keylist = ['bind', 'application level', 'binding']
    loc = [20, 96, 100, 101, 102, 104, 105, 115, 193, 434, 546]
    dd = DynamicNestedDict()
    dd.set_from_list(keylist, loc)
    result = dd.get_from_list(keylist)
    print("dd['bind']['application level']['binding']: {}".format(result))


if __name__ == '__main__':
    try_dynamic_nested_dict()


Possibly Related Threads…
Thread Author Replies Views Last Post
  Create Dynamic nested Dictionaries Larz60+ 8 9,005 Nov-26-2018, 12:58 AM
Last Post: DeaD_EyE

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020