【问题标题】:Python: Create dictionary recursively from "graph" (database) dataPython:从“图形”(数据库)数据递归创建字典
【发布时间】:2019-10-05 07:07:24
【问题描述】:

一个在 MySQL 数据库中映射的层次结构(我通过 Peewee 访问)。我正在尝试遍历数据以将其重新组合成嵌套字典(用于最终转换为 XML)。

以下函数将我的数据向下传递到父节点并打印出我想要在我的 dict 中结构化的数据:

def build_dict(current):
    query = (ParamLevel
            .select()
            # If we are looking for parents, we are matching on child
            .join(ParamLevelParamLevels, JOIN.LEFT_OUTER, on = (ParamLevelParamLevels.parent == ParamLevel.id))
            .where(ParamLevelParamLevels.child == current)
            )

    # If we have a parent node, recurse further
    if query.exists():
        parent = query.get()
        build_dict(parent)
        print('Current ParamLevel "%s" parent: "%s"' % ( current.name, parent.name ))
    else:
        print('Found root node: %s' % current.name)

这样做时,它会打印出来:

Found root node: polycomConfig
Current ParamLevel "device" parent: "polycomConfig"
Current ParamLevel "device.dhcp" parent: "device"
Current ParamLevel "device.dhcp.bootSrvOptType" parent: "device.dhcp"

我正在寻找有关如何生成以下数据结构的输入:

{polycomConfig : { device : { device.dhcp : { device.dhcp.bootSrvOptType: {} } } } }

我确信这相当简单,但我对实现递归函数感到生疏。

谢谢!

【问题讨论】:

    标签: python python-3.x dictionary recursion peewee


    【解决方案1】:

    使用while 循环而不是递归来执行此操作,并且只需构建嵌套的字典即可。在这种情况下,递归实际上没有任何好处。

    def build_dict(current):
        print(f'Found root node {current.name}')
        temp_dict = {}
        query = (ParamLevel
                .select()
                # If we are looking for parents, we are matching on child
                .join(ParamLevelParamLevels, JOIN.LEFT_OUTER, on = (ParamLevelParamLevels.parent == ParamLevel.id))
                .where(ParamLevelParamLevels.child == current)
                )
        while query.exists():
            result = query.get()
            temp_dict = {result.name: temp_dict}
            query = (ParamLevel
                .select()
                # If we are looking for parents, we are matching on child
                .join(ParamLevelParamLevels, JOIN.LEFT_OUTER, on = (ParamLevelParamLevels.parent == ParamLevel.id))
                .where(ParamLevelParamLevels.child == result)
                )
    

    没有办法对其进行测试,我无法为您提供输出,也无法检查任何错误,但您应该了解它的要点。你想要的结果应该在temp_dict

    我用这个测试过:

    d = {}
    for i in range(5):
        d = {i: d}
    print(d)
    

    输出:

    {4: {3: {2: {1: {0: {}}}}}}
    

    【讨论】:

    • 感谢您的回复。看着你的方法。 FWIW,就我而言,它给了我相反的顺序: {'device.dhcp': {'device': {'polycomConfig': {}}}} 我认为我认为递归的原因是“冒泡”并组装反过来。
    • 效果很好,也很容易理解。谢谢。
    【解决方案2】:

    如果没有一个好的例子很难尝试,但我相信这应该可行:

    def build_dict(current, root={}):
        query = (
            ParamLevel.select()
            # If we are looking for parents, we are matching on child
            .join(
                ParamLevelParamLevels,
                JOIN.LEFT_OUTER,
                on=(ParamLevelParamLevels.parent == ParamLevel.id),
            ).where(ParamLevelParamLevels.child == current)
        )
    
        # If we have a parent node, recurse further
        if query.exists():
            parent = query.get()
            root, parent_dict = build_dict(parent, root)
            parent_dict[parent.name] = {current.name: {}}
            return root, parent_dict[parent.name]
        else:
            root[current.name] = {}
            return root, root
    
    answer, _ = build_dict(<starting_node>)
    

    【讨论】:

    • 看看你的方法,谢谢。你的代码给了我: {'device.dhcp.bootSrvOptType': {'device.dhcp': {}}, 'device.dhcp': {'device': {}}, 'polycomConfig': {}, 'device' : {'polycomConfig': {}}} 这不是我所需要的。
    • @JoenarrBronarsson 我更新了它。仔细想想,您需要保留对根对象和每个“父对象”的引用,以便修改父对象并保留对根对象的引用。
    • 谢谢,还没有尝试,但非常感谢。
    猜你喜欢
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    相关资源
    最近更新 更多