I am trying to create a dictionary tree from child-parent relathionships but the issue here is that the child can contain one of his predecesors generating loops that I would like to avoid.
list_child_parent = [(2,1),(3,2),(4,2),(5,3),(6,4),(2,6)]
def make_map(list_child_parent):
has_parent = set()
all_items = {}
for child, parent in list_child_parent:
if parent not in all_items:
all_items[parent] = {}
if child not in all_items:
all_items[child] = {}
if parent not in all_items[child]:
all_items[parent][child] = all_items[child]
has_parent.add(child)
else:
continue
result = {}
for key, value in all_items.items():
if key not in has_parent:
result[key] = value
return result
make_map(list_child_parent)
The code works well if a son contains his father but not if it is the granfather...
I think another approach is needed.
The expected results could be any if it makes sense:
{1: {2: {3: {5: {}}, 4: {6: {}}}}}
{1: {2: {3: {5: {}}, 4: {6: 2}}}}
{1: {2: {3: {5: {}}, 4: {6: {2:{}}}}}}
The current result is:
{1: {2: {3: {5: {}}, 4: {6: {2: {...}}}}}}
You can use a set to keep track of all the children, so that you can make the dict of descendants an empty dict if the current child has previously been a child of another parent:
def make_map(list_child_parent):
mapping = {}
children = set()
for child, parent in list_child_parent:
mapping.setdefault(parent, {})[child] = (
{} if child in children
else mapping.setdefault(child, {})
)
children.add(child)
return {
parent: mapping[parent]
for parent in mapping.keys() - children
}
so that:
make_map([(2, 1), (3, 2), (4, 2), (5, 3), (6, 4), (2, 6)])
returns:
{1: {2: {3: {5: {}}, 4: {6: {2: {}}}}}}
Demo: Try it online!