Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding to a dict using a list of key strings as path

I have the following dict:

aDict = {
    "a" : {
        "b" : {
            "c1" : {},
            "c2" : {},
        }
    }
}

a second dict:

aSecondDict = { 
    "d1" : {},
    "d2" : {},
    "d3" : {},
}

and a "path" tuple:

path = ( "a", "b", "c2" )

I now want to add the second dict to the first at the path provided by the tuple:

aResultDict = {
    "a" : {
        "b" : {
            "c1" : {},
            "c2" : {
                "d1" : {},
                "d2" : {},
                "d3" : {},
            },
        }
    }
}

What is the pythonic way of achieving this?

like image 619
Juergen Riemer Avatar asked Apr 30 '13 12:04

Juergen Riemer


People also ask

Can you use a list as a key for a dictionary?

A dictionary or a list cannot be a key. Values, on the other hand, can literally be anything and they can be used more than once.

How do you append to a dictionary?

Appending element(s) to a dictionary To append an element to an existing dictionary, you have to use the dictionary name followed by square brackets with the key name and assign a value to it.

Can Python dictionary have list as keys?

We can use integer, string, tuples as dictionary keys but cannot use list as a key of it .

Is dict () and {} the same?

The setup is simple: the two different dictionaries - with dict() and {} - are set up with the same number of elements (x-axis). For the test, each possible combination for an update is run.


1 Answers

You can use reduce1 to get the dictionary and dict.update to put the new stuff in there:

reduce(lambda d,key: d[key],path,aDict).update(aSecondDict)

You can even get a little more clever if you want:

reduce(dict.__getitem__,path,aDict).update(aSecondDict)

I suppose it should be noted that the two approaches are slightly different. The latter forces aDict to only contain more dictionaries (or dict subclasses) whereas the former allows for anything which has a __getitem__ method to be in aDict. As noted in the comments, you could also use:

reduce(dict.get,path,aDict).update(aSecondDict)

However, this version will raise an AttributeError if you try to traverse a "link" in the path which is non-existent rather than a KeyError so I don't like it quite as much. This method also enforces that every value along the path is a dict or dict subclass.

1reduce is a builtin for python2.x. Starting at python2.6 it is also available as functools.reduce. Code which wants to be compatible with python3.x should try to use functools.reduce as the builtin is removed in python3.x

like image 149
mgilson Avatar answered Sep 27 '22 16:09

mgilson