如何将层次结构字典转换为识别文本和节点的格式?

How can I convert a hierarchy dictionary into a format identifying text and nodes?

我是 python 的新手,我正在寻找一种方法来使用一些代码将以下词典转换为下面概述的格式。

{'Parent 1': {'Child 1': {Grandchild 1: {}, 'Grandchild 2: {}}, 'Child 2': {}} Parent 2: {}}

然后将其转换为:

{
    'text': "Parent 1",
    'nodes': [
        {
            'text': "Child 1",
            'nodes': [
                {
                    'text': "Grandchild 1"
                },
                {
                    'text': "Grandchild 2"
                }
            ]
        },
        {
            'text': "Child 2"
        }
    ]
},
{
    'text': "Parent 2"
}

也许我不应该让它变得如此简单,但我会给你答案。实际上有两个。请研究这些,以便您学到一些东西。如果这是作业什么的,请不要只提交答案而不从中学习。

第一种方法是不用递归来解决问题。您只需逐级跟踪问题,执行您需要执行的操作以读取原始数据结构并生成新结构:

data = {'Parent 1': {'Child 1': {'Grandchild 1': {}, 'Grandchild 2': {}}, 'Child 2': {}}, 'Parent 2': {}}

parent_nodes = []
for parent_text, parent_data in data.items():
    parent_entry = {'text': parent_text}
    child_nodes = []
    for child_text, child_data in parent_data.items():
        child_entry = { 'text': child_text }
        grandchild_nodes = []
        for grandchild_text, grandchild_data in child_data.items():
            grandchild_entry = { 'text': grandchild_text }
            grandchild_nodes.append(grandchild_entry)
        if len(grandchild_nodes):
            child_entry['nodes'] = grandchild_nodes
        child_nodes.append(child_entry)
    if len(child_nodes):
        parent_entry['nodes'] = child_nodes
    parent_nodes.append(parent_entry)

print(json.dumps(parent_nodes, indent=4))

随着您成为一名更好的程序员,您将学会识别可让您减少代码大小并使其更通用的模式。在这种情况下,您可能会认识到此问题与具有遵循相同模式的多个级别的数据结构有关。您应该能够编写不仅可以处理三个级别,而且可以处理 4、5 或 100 个级别的代码。

执行此操作的方法是递归。你认识到你需要先处理一个较低层次,然后你才能完成较高层次的处理。在处理低层次的时候,你又认识了同样的东西,所以又是先处理低层次的。这是递归。下面的代码也可以执行您想要的操作,但使用递归:

data = {'Parent 1': {'Child 1': {'Grandchild 1': {}, 'Grandchild 2': {}}, 'Child 2': {}}, 'Parent 2': {}}

def do_one_level(data):
    nodes = []
    for text, entry in data.items():
        node = { 'text': text }
        subnode = do_one_level(entry)
        if len(subnode):
            node['nodes'] = subnode
        nodes.append(node)
    return nodes

parent_nodes = do_one_level(data)
print(json.dumps(parent_nodes, indent=4))

请注意,do_one_level() 函数会调用自身。这是递归。请记住,第二个版本“更好”的原因不仅仅是它的代码更少,更重要的是它可以处理输入数据结构中的任意数量的级别。

两个版本产生相同的输出:

[
    {
        "text": "Parent 1",
        "nodes": [
            {
                "text": "Child 1",
                "nodes": [
                    {
                        "text": "Grandchild 1"
                    },
                    {
                        "text": "Grandchild 2"
                    }
                ]
            },
            {
                "text": "Child 2"
            }
        ]
    },
    {
        "text": "Parent 2"
    }
]

请尝试以下代码。用 modify(input)

调用它

代码

def modify(input):
    return [{"text":key,"nodes":modify(value) if isinstance(value,dict) else value} if value else {"text":key} for key,value in input.items()]
    

输入

input={'Parent 1': {'Child 1': {'Grandchild 1': {}, 'Grandchild 2': {}}, 'Child 2': {}}, 'Parent 2': {}}

输出

[
  {
    "text": "Parent 1",
    "nodes": [
      {
        "text": "Child 1",
        "nodes": [
          {
            "text": "Grandchild 1"
          },
          {
            "text": "Grandchild 2"
          }
        ]
      },
      {
        "text": "Child 2"
      }
    ]
  },
  {
    "text": "Parent 2"
  }
]

注意:这里使用递归