Set values for empty list within nested dictionaries

Viewed 113

I have a cte query that returns me results of values that are linked (i.e. child -> parent).

Then in Python I am trying to create a nested dictionary that would represent something like this:

{
    "name": "Child_example",
    "parents": [
        {
            "name": "child_parent_1",
            "parents": [{"name": "child_parent_1_parent", "parents": [{"name": "end", "parents": []}]}]
        },
        {
            "name": "child_parent_2",
            "parents": [{"name": "end", "parents": []}]
        },
        {
            "name": "child_parent_3",
            "parents": [{"name": "child_parent_3_parent", "parents": [{"name": "end", "parents": []}]}]
        }
    ]
}

My input data looks something like so (it can have more data):

child_col parent_col name depth
Child_example child_parent_1_col child_parent_1 0
Child_example child_parent_2_col child_parent_2 0
Child_example child_parent_3_col child_parent_3 0
child_parent_1_col child_parent_1_parent 1_parent 1
child_parent_2_col end 1_parent 1
child_parent_3_col child_parent_3_parent 3_parent 1
child_parent_3_parent end end_3 2
child_parent_1_parent end end_1 2

However with my code so far:

        r_dict = defaultdict(list)
        depth_zero = [x for x in rows if x.depth == 0]
        for row in depth_zero:
            r_dict['name'] = row.path_key
            r_dict['parents'].append({'name': row.path_parent_key, 'parents': []})
        depth_not_zero = [x for x in rows if x.depth != 0]
        #  Set inner levels
        for parent in r_dict['parents']:
            name = parent['name']
            inner_parent = parent['parents'].copy()
            for row in depth_not_zero:
                if row.path_key == name:
                    inner_parent.append({'name': row.path_parent_key, 'parents': []})
                    name = row.path_parent_key
            parent['parents'] = inner_parent

I only manage to achieve to append it to initial "parents", instead of setting the ultimate nested "parents". I know it is to do with this line of code:

inner_parent.append({'name': row.path_parent_key, 'parents': []})

But I cannot work out how to essentially get and set it. Would this be a case for recursion instead of the way I am doing it?

Below is an example of the first nested dictionary output that I am currently creating with my code:

{
    "name": "Child_example",
    "parents": [
        {
            "name": "child_parent_1",
            "parents": [
                {"name": "child_parent_1", "parents": []}, {"name": "end", "parents": []}
            ]
        }
    ]
}
1 Answers

I'm a bit baffled by the way you are assigning the "name" value: "Child_example" comes from child_col, "child_parent_1" from name, "child_parent_3_parent" from parent_col. So I simplified it a bit: I put in the second column of the child row the same value as in the first column of its parents rows. That said, if you really need to take the names from different columns it's just a matter of adding some ifs.

My proposal is to loop over the rows in reverse order, creating the inner dicts and then moving them into the outer ones:

rows = [["c1","p1c1",0],
        ["c1","p2c1",0],
        ["c1","p3c1",0],
        ["p1c1","p1p1c1",1],
        ["p2c1","end",1],
        ["p3c1","p1p3c1",1],
        ["p1p3c1","end",2],
        ["p1p1c1","end",2]]

r_dict = {}
for row in reversed(rows):
    if row[1] == "end":
        r_dict[row[0]] = {"name":row[0], "parents":[]}
    else:
        if not row[0] in r_dict:
            r_dict[row[0]] = {"name":row[0], "parents":[]}
        r_dict[row[0]]["parents"].append(r_dict[row[1]])
        del r_dict[row[1]]
        
r_dict
{'c1': {'name': 'c1', 'parents': [{'name': 'p3c1', 'parents': [{'name': 'p1p3c1', 'parents': []}]}, {'name': 'p2c1', 'parents': []}, {'name': 'p1c1', 'parents': [{'name': 'p1p1c1', 'parents': []}]}]}}

Related