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

2019-06-16 03:41发布

问题:

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?

回答1:

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