Проверка словаря с использованием точечной нотации
Этот дует мой разум. Учитывая следующий словарь:
d = {"a":{"b":{"c":"winning!"}}}
У меня есть эта строка (из внешнего источника, и я не могу изменить эту метафору).
k = "a.b.c"
Мне нужно определить, есть ли у словаря ключ 'c', поэтому я могу добавить его, если это не так.
Это работает плавно для получения значения точечной нотации:
reduce(dict.get, key.split("."), d)
но я не могу понять, как "уменьшить" проверку has_key или что-то в этом роде.
Моя конечная проблема заключается в следующем: учитывая "a.b.c.d.e", мне нужно создать все элементы, необходимые в словаре, но не топать их, если они уже существуют. Если кто-то знает способ свиста, чтобы сделать все это, вы станете моим героем.
Ответы
Ответ 1
... или используя рекурсию:
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
Вы можете использовать бесконечный, вложенный 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'
Ответ 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
Ответ 4
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!'}}}"