递归访问字典和修改

时间:2014-04-11 11:18:02

标签: python dictionary

我有以下字典:

my_dict = {'key1': {'key2': {'foo': 'bar'} } }

我想在key1-> key2-> key3上添加一个条目,其值为' blah'得到以下特性:

my_dict = {'key1': {'key2': {'foo': 'bar', 'key3': 'blah'} } }

我正在寻找一个独立于密钥数量的通用解决方案,即key1-> key2-> key3-> key4-> key5应该也能正常工作,即使key3上的键位于向下也是如此不存在。所以我得到了:

my_dict = {'key1': {'key2': {'foo': 'bar', 'key3': {'key4': {'key5': 'blah'} } } } }

提前致谢。

2 个答案:

答案 0 :(得分:12)

您可以使用reduce() function遍历一系列嵌套词典:

def get_nested(d, path):
    return reduce(dict.__getitem__, path, d)

演示:

>>> def get_nested(d, path):
...     return reduce(dict.__getitem__, path, d)
... 
>>> my_dict = {'key1': {'key2': {'foo': 'bar', 'key3': {'key4': {'key5': 'blah'}}}}}
>>> get_nested(my_dict, ('key1', 'key2', 'key3', 'key4', 'key5'))
'blah'

当密钥不存在时,此版本抛出异常:

>>> get_nested(my_dict, ('key1', 'nonesuch'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in get_nested
KeyError: 'nonesuch'

但您可以将dict.__getitem__替换为lambda d, k: d.setdefault(k, {}),以使其创建空字典:

def get_nested_default(d, path):
    return reduce(lambda d, k: d.setdefault(k, {}), path, d)

演示:

>>> def get_nested_default(d, path):
...     return reduce(lambda d, k: d.setdefault(k, {}), path, d)
... 
>>> get_nested_default(my_dict, ('key1', 'nonesuch'))
{}
>>> my_dict
{'key1': {'key2': {'key3': {'key4': {'key5': 'blah'}}, 'foo': 'bar'}, 'nonesuch': {}}}

设置给定路径的值,遍历除最后一个键之外的所有键,然后在常规字典赋值中使用最终键:

def set_nested(d, path, value):
    get_nested_default(d, path[:-1])[path[-1]] = value

这使用get_nested_default()函数根据需要添加空字典:

>>> def set_nested(d, path, value):
...     get_nested_default(d, path[:-1])[path[-1]] = value
... 
>>> my_dict = {'key1': {'key2': {'foo': 'bar'}}}
>>> set_nested(my_dict, ('key1', 'key2', 'key3', 'key4', 'key5'), 'blah')
>>> my_dict
{'key1': {'key2': {'key3': {'key4': {'key5': 'blah'}}, 'foo': 'bar'}}}

答案 1 :(得分:1)

Martijn Pieters的另一个很好的答案是使用嵌套的defaultdict,而不是常规词典:

from collections import defaultdict

nested = lambda: defaultdict(nested) # nested dictionary factory

my_dict = nested()

您可以使用常规嵌套字典访问语义来设置值,并且将创建空字典以根据需要填充中间级别:

my_dict["key1"]["key2"]["key3"] = "blah"

当然,当您编写代码来设置值时,这需要事先知道密钥的数量。如果您希望能够处理可变长度的键列表而不是固定的数字,那么您需要使用函数来为您进行获取和设置,例如在Martijn的答案中。

相关问题