这个让我大吃一惊。鉴于以下字典:
d = {"a":{"b":{"c":"winning!"}}}
我有这个字符串(来自外部来源,我不能改变这个比喻)。
k = "a.b.c"
我需要确定字典是否有密钥'c',所以如果没有,我可以添加它。
这可以游戏地检索点符号值:
reduce(dict.get, key.split("."), d)
但我无法弄清楚如何'减少'has_key检查或类似的东西。
我的最终问题是:给定“a.b.c.d.e”,我需要在字典中创建所有必要的元素,但如果它们已经存在则不要踩它们。如果有人知道做出这一切的真正方式,你就会成为我的英雄。
答案 0 :(得分:22)
您可以使用无限的嵌套defaultdict:
>>> from collections import defaultdict
>>> infinitedict = lambda: defaultdict(infinitedict)
>>> d = infinitedict()
>>> d['key1']['key2']['key3']['key4']['key5'] = 'test'
>>> d['key1']['key2']['key3']['key4']['key5']
'test'
鉴于你的虚线,这是你可以做的:
>>> import operator
>>> keys = "a.b.c".split(".")
>>> lastplace = reduce(operator.getitem, keys[:-1], d)
>>> lastplace.has_key(keys[-1])
False
您可以设置一个值:
>>> lastplace[keys[-1]] = "something"
>>> reduce(operator.getitem, keys, d)
'something'
>>> d['a']['b']['c']
'something'
答案 1 :(得分:11)
...或使用递归:
def put(d, keys, item):
if "." in keys:
key, rest = keys.split(".", 1)
if key not in d:
d[key] = {}
put(d[key], rest, item)
else:
d[keys] = item
def get(d, keys):
if "." in keys:
key, rest = keys.split(".", 1)
return get(d[key], rest)
else:
return d[keys]
答案 2 :(得分:3)
迭代方法怎么样?
def create_keys(d, keys):
for k in keys.split("."):
if not k in d: d[k] = {} #if the key isn't there yet add it to d
d = d[k] #go one level down and repeat
如果您需要将最后一个键值映射到除字典以外的任何内容,您可以将该值作为附加参数传递,并在循环之后设置它:
def create_keys(d, keys, value):
keys = keys.split(".")
for k in keys[:-1]:
if not k in d: d[k] = {}
d = d[k]
d[keys[-1]] = value
答案 3 :(得分:0)
d = {"a":{}}
k = "a.b.c".split(".")
def f(d, i):
if i >= len(k):
return "winning!"
c = k[i]
d[c] = f(d.get(c, {}), i + 1)
return d
print f(d, 0)
"{'a': {'b': {'c': 'winning!'}}}"