Is there a recursive version of the dict.get() built-in?

后端 未结 6 709
别那么骄傲
别那么骄傲 2020-11-27 05:53

I have a nested dictionary object and I want to be able to retrieve values of keys with an arbitrary depth. I\'m able to do this by subclassing dict:



        
6条回答
  •  庸人自扰
    2020-11-27 06:01

    @ThomasOrozco's solution is correct, but resorts to a lambda function, which is only necessary to avoid TypeError if an intermediary key does not exist. If this isn't a concern, you can use dict.get directly:

    from functools import reduce
    
    def get_from_dict(dataDict, mapList):
        """Iterate nested dictionary"""
        return reduce(dict.get, mapList, dataDict)
    

    Here's a demo:

    a = {'Alice': {'Car': {'Color': 'Blue'}}}  
    path = ['Alice', 'Car', 'Color']
    get_from_dict(a, path)  # 'Blue'
    

    If you wish to be more explicit than using lambda while still avoiding TypeError, you can wrap in a try / except clause:

    def get_from_dict(dataDict, mapList):
        """Iterate nested dictionary"""
        try:
            return reduce(dict.get, mapList, dataDict)
        except TypeError:
            return None  # or some other default value
    

    Finally, if you wish to raise KeyError when a key does not exist at any level, use operator.getitem or dict.__getitem__:

    from functools import reduce
    from operator import getitem
    
    def getitem_from_dict(dataDict, mapList):
        """Iterate nested dictionary"""
        return reduce(getitem, mapList, dataDict)
        # or reduce(dict.__getitem__, mapList, dataDict)
    

    Note that [] is syntactic sugar for the __getitem__ method. So this relates precisely how you would ordinarily access a dictionary value. The operator module just provides a more readable means of accessing this method.

提交回复
热议问题