从平面字典创建嵌套字典

3

我有一个字典,其中是父类,是继承自它们的子类列表。

{
    "Animal": 
        ["Dog"]
    ,  
    "Dog": 
        ["Labrador"]
    , 
    "Vehicle": 
        ["PetrolCar", 
        "DieselCar"]
    ,
    "DieselCar": 
        ["Hyundai"]
    , 
    "PetrolCar": 
        ["Hyundai", 
        "Ford"]
}

正如您所看到的,一些父类也是另一个父类的子类(深层继承),即 Animal -> Dog -> Labrador

我该如何格式化输出以代表继承级别,就像这样:

{
    "Animal": {
        "Dog": { 
            "Labrador": []
        }
    }, 
    "Vehicle": {
        "PetrolCar": {
            "Hyundai": [], 
            "Ford": []
        },
        "DieselCar": { 
            "Hyundai": []
        }
    }
}

我还希望能够通过添加更多的父项或子项来扩展提供的数据集。例如:将 ElectricCar 添加为 Vehicle 的子项,将 Tesla 添加为 ElectricCar 的子项;将 Cat 添加为 Animal 的子项,但它本身没有子项。

输入:

{
    "Animal": 
        ["Dog",
        "Cat"]
    ,  
    "Dog": 
        ["Labrador"]
    , 
    "Vehicle": 
        ["PetrolCar", 
        "DieselCar",
        "ElectricCar"]
    ,
    "DieselCar": 
        ["Hyundai"]
    , 
    "PetrolCar": 
        ["Hyundai", 
        "Ford"]
    ,
    "ElectricCar": 
        ["Tesla"]
}

输出:

{
    "Animal": {
        "Dog": { 
            "Labrador": []
        },
        "Cat": []
    }, 
    "Vehicle": {
        "PetrolCar": {
            "Hyundai": [], 
            "Ford": []
        },
        "DieselCar": { 
            "Hyundai": []
        },
        "ElectricCar": { 
            "Tesla": []
        }
    }
}

1
你可以从初始字典构建一个图,然后通过深度优先搜索遍历子节点,在此过程中构建最终的字典。 - rafaelc
1个回答

5
你可以使用递归来生成嵌套字典,然后删除没有子项的键:
data = {'Animal': ['Dog', 'Cat'], 'Dog': ['Labrador'], 'Vehicle': ['PetrolCar', 'DieselCar', 'ElectricCar'], 'DieselCar': ['Hyundai'], 'PetrolCar': ['Hyundai', 'Ford'], 'ElectricCar': ['Tesla']}
def build(key):
  return {i:[] if i not in data else build(i) for i in data[key]}

results = {i:build(i) for i in data}

import json
print(json.dumps({a:b for a, b in results.items() if any(h for h in b.values())}, indent=4))

输出:

{
  "Animal": {
    "Dog": {
        "Labrador": []
    },
    "Cat": []
  },
  "Vehicle": {
    "PetrolCar": {
        "Hyundai": [],
        "Ford": []
     },
     "DieselCar": {
        "Hyundai": []
     },
     "ElectricCar": {
        "Tesla": []
     }
   }
}

谢谢!你能再详细解释一下这个是如何工作的吗?它对于提供的示例确实有效,但是当我添加另一个Vehicle的子项时,它会失败,因此我想调整您的代码,使其适用于任何提供的数据集。 - Gary
@Gary 谢谢。"ElectricCar"没有被包含在最终输出中的原因是因为它不在"Vehicle"的子级中出现,因此在build循环中没有被访问到。但是,如果您将"ElectricCar"添加到"Vehicle"下的列表中,则会产生所需的输出。请查看我的最近编辑,我已经发布了这个结果。 - Ajax1234
是的,抱歉,您的原始代码按预期工作。还有一个问题 - 我该如何使树的所有元素都具有子元素列表,如果子元素没有任何子元素,则可以为空?我会将此添加到原始帖子中。 - Gary
很好的回答。在“猫”键之前,应该有一个逗号来分隔“狗”值字典吧? - Gary
@Gary 很高兴能帮忙! - Ajax1234
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接