递归地遍历N个嵌套字典并创建N + 1个嵌套字典

时间:2020-09-23 07:54:11

标签: python dictionary

我有一个文件:

Key1:
    Key2:
        Key3:
            Key4: Value4

我正在逐行阅读文件:

with open(configuration_file) as config_file:
    nested_dict = {}
    for line in config_file:
        dict_reader(line)

每行都要通过此功能dict_reader我想将每行添加到N嵌套字典中。

def dict_reader(line):
    if ": " in line and not ": &" in line and not ": *" in line:
        # create key-value pair, add it to the last empty dictionary in nested_dict   
    if ":" in line and not ": " in line:
        if nested_dict:
            key2 = str(line.split(':')[0].strip())
            d = {key2: {}}

            for k, v in nested_dict.items():
                if isinstance(v, dict):
                    v.update(d)
                    break
            print(nested_dict)

        else:
            key1 = str(line.split(':')[0])
            nested_dict[key1] = {}

第一次运行后,将返回:{'Key1': {}},这就是我所追求的

第二次运行后,返回:{'Key1': {'Key2': {}}}也是我所追求的

但是在第三次及其后的运行之后,它返回:{'Key1': {'Key2': {}, 'Key3': {}}}。它没有将{'Key3': {}}作为'Key2'的值,而是将其作为该字典中的另一个元素返回。对于'Key4',例如

{'Key1': {'Key2': {}, 'Key3': {}, 'Key4': {}}}

每行之后,应该只有一个空字典:

{'Key1': {}}
{'Key1': {'Key2': {}}}
{'Key1': {'Key2': {'Key3': {}}}}
{'Key1': {'Key2': {'Key3': {'Key4': {}}}}}
 etc.

对于每个循环,我想搜索N个嵌套字典,找到一个空字典的第一个匹配项(只有一个),然后将空字典更新为我刚刚从文件中读取的行。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

问题出在for循环中。

在循环的第三遍调用v.update(d)

  • d = {'Key3': {}}
  • v = {'Key2': {}}

请记住k, v,您正在遍历nested_dict项的{'Key1': {'Key2': {}}}项。

v.update(d)更改为v = {'Key2': {}, 'Key3': {}}

为什么?根据方法文档字符串,D.update(E)根据输入有一些不同的行为。在这种情况下:

“如果E存在并且具有.keys()方法,则执行:for k in E: D[k] = E[k]”。

因此,在这种情况下,它仅将'Key3': {}对添加到v,其中v实际上只是引用了nested_dict中持有的值(该值只有一个键值对)。


如果我正确理解,在您的示例中,您正在编写一个打算复制load库中的yaml函数的函数。

我假定将其写为 point ,因为您不想使用该库-为了他人的利益,可以按以下步骤进行操作:

import yaml

data = """
Key1:
    Key2:
        Key3:
            Key4: Value4
"""

parsed = yaml.load(data)

# parsed = {'Key1': {'Key2': {'Key3': {'Key4': 'Value4'}}}}

由于您不想这样做,因此您需要仔细阅读字典,直到达到最深的层次为止,而不是for k, v in nested_dict.items()。问题是,您事先不知道将要达到多少个级别。我建议您可以定义如下函数:

def get_deepest_level(d): 
     if not isinstance(d, dict):
         return d  # if the value isn't a dict, just return it
     # otherwise continue:
     for k, v in d.items(): 
         if v: 
             return get_deepest_level(v)  # recursion!
         else: 
             return v 

这将继续在嵌套级别中下拉,直到遇到不是字典或空字典的值-这些值中的任何一个都将在顶层返回。如果您致电

deepest_level = get_deepest_level(nested_dict)

deepest_level.update(d)

这将更新它可能找到的最深入嵌套的字典(请记住,其中的项目之间总是存在循环,这些项目将始终落入您的第一个键值对中……但这仍然是您正在做的事情)