以编程方式访问字典中任意深度嵌套的值

5
我正在编写一个Python脚本,其中我会得到一些字符串列表,格式如下:['key1', 'key2', 'key2.key21.key211', 'key2.key22', 'key3']
列表中的每个值对应字典中的一个条目,对于像'key2.key21.key211'这样结构化的条目,它们对应于(在此示例中)嵌套在'key21'内部的'key211'键,该键本身又嵌套在'key2'内部。
上面的列表对应以下字典:
x = {
     'key1' : 'value1',
     'key2' : {
               'key21' : {
                          'key211': 'value211'
                         },
               'key22' : 'value22'
              },
     'key3' : 'value3'
    }

名字可能并不像 key(n)+ 那样规律,比如可以是 food.vegetables.potato 的形式。唯一确定的是,在字典中,键名本身 不包含 . 字符,并且该字典中确实包含原始列表中引用的所有条目。

我的问题是,给定这样一个字符串列表,如何以编程方式访问字典中相应的条目?我能想到使用 eval() 的解决方案,还有一种只使用遍历/搜索的方法,但我想避免调用 eval(),而且我认为遍历和比较会很慢(因为 dict 不是搜索树),并且需要处理很多令人讨厌的异常情况。


1
你应该先尝试一下,然后编辑问题以包括你编写的代码。 - quamrana
让我看看我是否正确理解了你的问题:你需要做的是将每个键(字符串)拆分为“。”,然后对于所有结果k,访问original_dict[k[0]][k[1]][k[2]]... - Two-Bit Alchemist
@Two-Bit 确实如此。quamrana 我会在半小时内更新一个初步的解决方案。 - Jules
1
你说的“搜索”是什么意思?因为每个级别都有一个键,所以检索值是一个O(1)操作。 - jonrsharpe
@jonrsharpe 但是据我所知,Python没有以编程方式访问任意深度键的功能。 - Jules
2
它没有dict方法,但编写一个迭代/递归函数应用它很容易。 - jonrsharpe
1个回答

9
一种方法是编写一个函数来访问嵌套字典中的键。
def deep_access(x,keylist):
     val = x
     for key in keylist:
         val = val[key]
     return val

s = 'key2.key21.key211'

print deep_access(x,s.split('.'))

结果:

value211

如果您想使用类似于普通字典访问的语法,另一种方法是继承dict并覆盖__getitem__,以允许在提供键元组时进行嵌套访问:

class NestedDict(dict):

    def __getitem__(self,keytuple):
        # if key is not a tuple then access as normal
        if not isinstance(keytuple, tuple):
            return super(NestedDict,self).__getitem__(keytuple)
        d = self
        for key in keytuple:
            d = d[key]
        return d

>>> nd = NestedDict(x)
>>> nd['key2']
{'key22': 'value22', 'key21': {'key211': 'value211'}}
>>> nd['key2','key22']
'value22'
>>> nd['key2','key21']
{'key211': 'value211'}
>>> nd['key2','key21','key211']
'value211'

随后您可以根据需要类似地实现__setitem____delitem__


这个第二个解决方案非常有用,我在想为什么它不在某种库中可用呢? - atomic77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接