Python中的嵌套字典:分配键,但保持子结构

时间:2016-09-29 07:10:40

标签: python dictionary nested key assign

我正在使用Python 3.5,我在向字典键分配值时遇到问题。我的字典结构如下:

dict_var = {'file':
               {'index':
                    {'flag':
                         {'flag_key': 'False'},
                     'attr':
                         {'attr_key': 'attr_val'},
                     'path':
                         {'path_key': 'path_val'},
                     }
                }
            }

我得到KeyError:1,如果我更改嵌套密钥'index',如下所示:

dict_var['file']['1']['flag'] = 'some value'
dict_var['file']['2']['flag'] = 'some value'
dict_var['file']['3']['flag'] = 'some value'
dict_var['file']['4']['flag'] = 'some value'

或者如果我尝试更改嵌套密钥'flag'

dict_var['file']['index']['flag_2']['flag_key'] = 'some value'

有没有办法为嵌套键分配新名称,但保留以下子键和值的结构,就像在我的示例中一样? 我希望有人可以帮助我。非常感谢和提前致以最好的问候

2 个答案:

答案 0 :(得分:3)

您可以使用嵌套的defaultdict,如下所示:

from collections import defaultdict

ndefaultdict = lambda:defaultdict(ndefaultdict)

dict_var = ndefaultdict()
dict_var['file']['1']['flag'] = 'some value'
dict_var['file']['2']['flag'] = 'some value'
dict_var['file']['3']['flag'] = 'some value'
dict_var['file']['4']['flag'] = 'some value'

然后,您可以编写一个简单的循环,将原始字典中的信息传输到嵌套字典中。 一个示例解决方案:

from collections import defaultdict

def ndefaultdict(orig_dict):
    l = lambda: defaultdict(l)
    out = l()

    def n_helper(orig_dict, nesteddict):
        for k, v in orig_dict.items():
            if isinstance(v, dict):
                n_helper(v, nesteddict[k])
            else:
                nesteddict[k] = v
        return nesteddict

    return n_helper(orig_dict, out)

# dict_var is the original dictionary from the OP.
new_dict = n_defaultdict(dict_var)
new_dict['foo']['bar']['baz'] = 'It works!!'

print( new_dict['file']['index']['attr']['attr_key']) # attr_val

编辑:

this SO thread,我找到了另外两个优雅的解决方案:

  1. 来自用户Vincent
  2. 使用defaultdict的简短解决方案

    from collections import defaultdict
    
    def superdict(arg=()):
        update = lambda obj, arg: obj.update(arg) or obj
        return update(defaultdict(superdict), arg)
    
    >>> d = {"a":1}
    >>> sd = superdict(d)
    >>> sd["b"]["c"] = 2
    
    1. 来自用户Dvd Avins
    2. 使用自定义NestedDict类。

      >>> class NestedDict(dict):
      ...     def __getitem__(self, key):
      ...         if key in self: return self.get(key)
      ...         return self.setdefault(key, NestedDict())
      
      
      >>> eggs = NestedDict()
      >>> eggs[1][2][3][4][5]
      {}
      >>> eggs
      {1: {2: {3: {4: {5: {}}}}}}
      

答案 1 :(得分:1)

您可以简单地将值传输到新密钥,然后删除旧密钥。例如:

dict_var['file']['1'] = dict_var['file']['index']
del dict_var['file']['index']