有这样的字典
my_pets = {
'Rudolf': {
'animal': 'cat',
'legs': 4
}
}
达到以下相同的清洁方式是什么?
my_pets['Rudolf']['legs']['front-right']['injured'] = True
my_pets['Rudolf']['legs']['front-left']['injured'] = False
它应该更新为
my_pets = {
'Rudolf': {
'animal': 'cat',
'legs': {
'front-right': {'injured':True},
'front-left': {'injured':False}
}
}
}
答案 0 :(得分:4)
你可以创建一个“无限”的默认指令,如下所示:
from collections import defaultdict
def infinidict():
return defaultdict(infinidict)
然后写:
>>> my_pets = infinidict()
>>> my_pets['Rudolf']['animal'] = 'cat'
>>> my_pets['Rudolf']['weight'] = 3
>>> my_pets['Rudolf']['legs']['front-right']['injured'] = True
>>> my_pets
defaultdict(<function __main__.infinidict>,
{'Rudolf': defaultdict(<function __main__.infinidict>,
{'animal': 'cat',
'legs': defaultdict(<function __main__.infinidict>,
{'front-right': defaultdict(<function __main__.infinidict>,
{'injured': True})}),
'weight': 3})})
输出看起来很混乱,但my_pets
只能在需要dict
的地方使用。
答案 1 :(得分:4)
下面是一个字典子类,它对于缺少任意深度的键很宽松:
d = freedict()
d['one']['two']['three'] = 1
d.one.two.three = 2
这可以像这样使用(对键的属性访问是个人偏好):
{{1}}
答案 2 :(得分:1)
这是一个非常有趣且非常实际的情况。 有许多实现都解决了某些问题,并错过了一些边缘场景。
可以在这些标题中找到可能的解决方案和不同的答案。
What is the best way to implement nested dictionaries?
What's the best way to initialize a dict of dicts in Python?
此外,还有许多关于此要求的博客和博客&#39; autovivification&#39;包括维基百科的存在。
http://blog.yjl.im/2013/08/autovivification-in-python.html
https://news.ycombinator.com/item?id=3881171
https://gist.github.com/hrldcpr/2012250
虽然上述实现方便一旦边缘情况仍然存在问题。在撰写本文时,没有任何实现已经很好地处理了是否存在原始坐位和阻塞嵌套。
以下是在StackOverflow中回答此问题和相关问题的3种主要方式。
编写一个辅助方法,它接受字典,值和嵌套键列表 适用于普通的dict对象,但缺少通常的方括号语法,
使用Defaultdict并编写自定义类,从根本上说这是有效的,因为默认dict为缺少的键提供{} 很棒的语法,但仅适用于使用自定义类创建的对象。
使用元组存储和检索(https://stackoverflow.com/a/651930/968442) 最糟糕的想法,甚至不应该声称是解决方案,这就是为什么
mydict = {}
mydict['foo', 'bar', 'baz'] = 1
print mydict['foo', 'bar', 'baz']
工作正常,但当您访问mydict['foo', 'bar']
时,期望为{'baz':1}
,而不是KeyError
这基本上摧毁了可迭代的概念。嵌套结构
在这三种方法中,我的选择是选项1.通过编写一个小辅助方法,边缘情况可以用实际方法解决,这是我的实现。
def sattr(d, *attrs):
# Adds "val" to dict in the hierarchy mentioned via *attrs
for attr in attrs[:-2]:
# If such key is not found or the value is primitive supply an empty dict
if d.get(attr) is None or isinstance(d.get(attr), dict):
d[attr] = {}
d = d[attr]
d[attrs[-2]] = attrs[-1]
现在
my_pets = {'Rudolf': {'animal': 'cat', 'legs': 4}}
sattr(my_pets, 'Rudolf', 'legs', 'front-right', 'injured', True)
sattr(my_pets, 'Rudolf', 'legs', 'front-left', 'injured', False)
将产生
{'Rudolf': {'legs': 4, 'animal': 'cat'}}
{'Rudolf': {'legs': {'front-right': {'injured': True}}, 'animal': 'cat'}}
{'Rudolf': {'legs': {'front-left': {'injured': False}, 'front-right': {'injured': True}}, 'animal': 'cat'}}
答案 3 :(得分:0)
尝试使用try
try:
# checks whether 'front-right' exists. If exists assigns value. Else raises exception
my_pets['Rudolf']['legs']['front-right']= {'injured':True}}
except:
# On raising exception add 'front-right' to 'legs'
my_pets['Rudolf']['legs'] = {'front-right': {'injured':True}}
这应该有效
答案 4 :(得分:0)
这将允许您根据列表的任意深度向dict添加一个键 按键。
def add_multi_key(subscripts, _dict={}, val=None):
"""Add an arbitrary length key to a dict.
Example:
out = add_multi_key(['a','b','c'], {}, 1 )
out -> {'a': {'b': {'c':1}}}
Arguments:
subscripts, list of keys to add
_dict, dict to update. Default is {}
val, any legal value to a key. Default is None.
Returns:
_dict - dict with added key.
"""
if not subscripts:
return _dict
subscripts = [s.strip() for s in subscripts]
for sub in subscripts[:-1]:
if '_x' not in locals():
if sub not in _dict:
_dict[sub] = {}
_x = _dict.get(sub)
else:
if sub not in _x:
_x[sub] = {}
_x = _x.get(sub)
_x[subscripts[-1]] = val
return _dict