简体   繁体   中英

Create dictionary recursively from "graph" (database) data

A have a hierarchical structure mapped out in a MySQL database (that I am accessing via Peewee). I am trying to traverse the data to re-assemble it into nested dictionaries (for final conversion into XML).

The below function walks my data down to the parent node and prints out the data I want structured in my 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)

In doing so, it prints this out:

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

I am looking for input on how to generate the below data structure:

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

I'm sure this is fairly straightforward but I'm rusty on implementing recursive functions.

Thanks!

Do it with a while loop instead of recursion and just build the nested dict as you go. Recursion doesn't have really any benefit in this case.

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)
            )

Without having a way to test it I can't give you the output nor check for any bugs but you should get the gist of it. The result you want should be in temp_dict .

I tested it with this:

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

Output:

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

Hard to try this without a good example, but I believe this should work:

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>)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM