在给定索引和值列表的情况下,在嵌套的python字典中设置值

pet*_*erk 30 python dictionary list

很抱歉,如果之前已经回答过这个问题 - 我一直在寻找解决方案,但我可能没有使用正确的搜索字词.

无论如何,我要做的是在给定索引列表和值的情况下以编程方式在字典中设置值,可能是嵌套的.

例如,假设我的索引列表是:

['person', 'address', 'city'] 
Run Code Online (Sandbox Code Playgroud)

而且价值是

'New York'
Run Code Online (Sandbox Code Playgroud)

我想要一个字典对象,如:

{ 'Person': { 'address': { 'city': 'New York' } }
Run Code Online (Sandbox Code Playgroud)

基本上,列表表示嵌套字典中的"路径".

我想我可以构建字典本身,但我磕磕绊绊的是如何设置值.显然,如果我只是手动编写代码,那将是:

dict['Person']['address']['city'] = 'New York'
Run Code Online (Sandbox Code Playgroud)

但是,如果我只有一个索引和值的列表,我如何索引到字典并以编程方式设置值?

希望这是有道理的,并不是一个愚蠢的问题... :)谢谢你的帮助.

Bak*_*riu 46

这样的事情可能会有所帮助:

def nested_set(dic, keys, value):
    for key in keys[:-1]:
        dic = dic.setdefault(key, {})
    dic[keys[-1]] = value
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

>>> d = {}
>>> nested_set(d, ['person', 'address', 'city'], 'New York')
>>> d
{'person': {'address': {'city': 'New York'}}}
Run Code Online (Sandbox Code Playgroud)

  • @charisz这是有效的,因为在`for`看起来你重新分配`dic`变量指向内部字典.在示例中,当设置`nested_set`时,最初你有`dic == d`.然后,`for`循环执行这增加了所述一对` "人" 的呼叫`DIC = dic.setdefault( "人物",{})`:{}``到和D`也*返回引用`{}`*.现在`DIC是d ["人"]`,因此下一个循环中设定的内字典中的键`address`,设置`dic`指向内内字典.等等.最后一个键以特殊方式处理,因为您不想再创建字典了. (5认同)
  • 任何线索请为什么这样有效?(我试过它与工程),以及为什么一个纯粹的for循环不? (2认同)
  • @nehemiah 这与问题要求的行为不同。如您所见,它在实现中增加了相当多的复杂性。 (2认同)

Jac*_*eur 5

我从Bakuriu 的回答中自由地扩展了代码。因此,对此的支持是可选的,因为他的代码本身就是一个机智的解决方案,这是我没想到的。

def nested_set(dic, keys, value, create_missing=True):
    d = dic
    for key in keys[:-1]:
        if key in d:
            d = d[key]
        elif create_missing:
            d = d.setdefault(key, {})
        else:
            return dic
    if keys[-1] in d or create_missing:
        d[keys[-1]] = value
    return dic
Run Code Online (Sandbox Code Playgroud)

设置create_missing为 True 时,您确保仅设置现有值:

# Trying to set a value of a nonexistent key DOES NOT create a new value
print(nested_set({"A": {"B": 1}}, ["A", "8"], 2, False))
>>> {'A': {'B': 1}}

# Trying to set a value of an existent key DOES create a new value
print(nested_set({"A": {"B": 1}}, ["A", "8"], 2, True))
>>> {'A': {'B': 1, '8': 2}}

# Set the value of an existing key
print(nested_set({"A": {"B": 1}}, ["A", "B"], 2))
>>> {'A': {'B': 2}}
Run Code Online (Sandbox Code Playgroud)