14

次の辞書を考えます。

d = {"a":{"b":{"c":"winning!"}}}

私はこの文字列を持っています (外部ソースからのもので、この比喩を変更することはできません)。

k = "a.b.c"

辞書に key がある 'c'かどうかを判断する必要があるため、ない場合は追加できます。

これは、ドット表記の値を取得するためにスムーズに機能します。

reduce(dict.get, key.split("."), d)

has_keyしかし、チェックなどを「減らす」方法がわかりません。

私の究極の問題は次のとおりです。与えられた場合、辞書に必要なすべての要素"a.b.c.d.e"を作成する必要がありますが、それらが既に存在する場合はそれらを踏みにじる必要はありません。

4

5 に答える 5

26

無限にネストされた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'
于 2012-09-13T21:16:05.133 に答える
15

...または再帰を使用する:

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]
于 2012-09-13T21:49:04.933 に答える
4

反復的なアプローチはどうですか?

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
于 2012-09-13T21:14:13.693 に答える
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!'}}}"
于 2012-09-13T22:37:28.503 に答える