I am trying to build a hierarchy graph from a list of strings I have. Each string just consists of its absolute hierarchy seperated by dots. Example Strings:
memberA.memberB.memberC
memberA.memberE.memberG
memberA.memberE
memberA.memberB
memberA.memberF.memberX
memberA.memberF
memberA.memberF.memberG #in this case this should be treated as a seperate leaf node and not the same as in memberA.memberE.memberG
I tried using Anytree and Treelib to achieve this but I could not come up with a working solution. Although this problem looks simple (might not be) I just can not figure it out.
CodePudding user response:
You'd need to keep track of which node objects correspond to a certain path. For that you can use a dictionary, that maps a given path to a node object.
With AnyTree it could look like this:
from anytree import Node, RenderTree
strings = [
"memberA.memberB.memberC",
"memberA.memberE.memberG",
"memberA.memberE",
"memberA.memberB",
"memberA.memberF.memberX",
"memberA.memberF",
"memberA.memberF.memberG"
]
d = {}
root = Node("root")
for s in strings:
path = "root"
parent = root
for name in s.split("."):
path = "." name
if path not in d:
d[path] = Node(name, parent=parent)
parent = d[path]
print(RenderTree(root))
Output:
Node('/root')
└── Node('/root/memberA')
├── Node('/root/memberA/memberB')
│ └── Node('/root/memberA/memberB/memberC')
├── Node('/root/memberA/memberE')
│ └── Node('/root/memberA/memberE/memberG')
└── Node('/root/memberA/memberF')
├── Node('/root/memberA/memberF/memberX')
└── Node('/root/memberA/memberF/memberG')
In case you want "memberA" to be the root, then you need to make sure your input data only has strings that start with "memberA". And then at the end of the above script do:
root = root.children[0]
root.parent = None
print(RenderTree(root))
Output:
Node('/memberA')
├── Node('/memberA/memberB')
│ └── Node('/memberA/memberB/memberC')
├── Node('/memberA/memberE')
│ └── Node('/memberA/memberE/memberG')
└── Node('/memberA/memberF')
├── Node('/memberA/memberF/memberX')
└── Node('/memberA/memberF/memberG')