Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking a nested dictionary using a dot notation string "a.b.c.d.e", automatically create missing levels

Given the following dictionary:

d = {"a":{"b":{"c":"winning!"}}}

I have this string (from an external source, and I can't change this metaphor).

k = "a.b.c"

I need to determine if the dictionary has the key 'c', so I can add it if it doesn't.

This works swimmingly for retrieving a dot notation value:

reduce(dict.get, key.split("."), d)

but I can't figure out how to 'reduce' a has_key check or anything like that.

My ultimate problem is this: given "a.b.c.d.e", I need to create all the elements necessary in the dictionary, but not stomp them if they already exist.

like image 802
hikaru Avatar asked Sep 13 '12 21:09

hikaru


People also ask

Can I access Python dictionary with dot?

Switching to Python, bad news : dot notation is not directly available with the resulting dictionary.

What is a nested dictionary explain with an example?

Nested Dictionary: Nesting Dictionary means putting a dictionary inside another dictionary. Nesting is of great use as the kind of information we can model in programs is expanded greatly.

Is nested dictionary possible?

Nested dictionary is an unordered collection of dictionary. Slicing Nested Dictionary is not possible. We can shrink or grow nested dictionary as need. Like Dictionary, it also has key and value.


2 Answers

You could use an infinite, nested defaultdict:

>>> from collections import defaultdict
>>> infinitedict = lambda: defaultdict(infinitedict)
>>> d = infinitedict()
>>> d['key1']['key2']['key3']['key4']['key5'] = 'test'
>>> d['key1']['key2']['key3']['key4']['key5']
'test'

Given your dotted string, here's what you can do:

>>> import operator
>>> keys = "a.b.c".split(".")
>>> lastplace = reduce(operator.getitem, keys[:-1], d)
>>> lastplace.has_key(keys[-1])
False

You can set a value:

>>> lastplace[keys[-1]] = "something"
>>> reduce(operator.getitem, keys, d)
'something'
>>> d['a']['b']['c']
'something'
like image 108
jterrace Avatar answered Oct 02 '22 17:10

jterrace


... or using recursion:

def put(d, keys, item):
    if "." in keys:
        key, rest = keys.split(".", 1)
        if key not in d:
            d[key] = {}
        put(d[key], rest, item)
    else:
        d[keys] = item

def get(d, keys):
    if "." in keys:
        key, rest = keys.split(".", 1)
        return get(d[key], rest)
    else:
        return d[keys]
like image 39
tobias_k Avatar answered Oct 02 '22 17:10

tobias_k