9

Is there a way to read data from a file and construct a tree using anytree?

Parent Child
A      A1
A      A2
A2     A21

I can do it with static values as follows. However, I want to automate this by reading the data from a file with anytree.

>>> from anytree import Node, RenderTree
>>> A = Node("A")
>>> A1 = Node("A1", parent=A)
>>> A2 = Node("A2", parent=A)
>>> A21 = Node("A21", parent=A2)

Output is

A
├── A1
└── A2
    └── A21
hshantanu
  • 424
  • 1
  • 8
  • 29

1 Answers1

9

This assumes that the entries are in such an order that a parent node was always introduced as a child of another node beforehand (root excluded).

With that in mind, we can then iterate over the lines, split them (I used split, regex would work too) and create the new nodes.

For how to get a reference to the parent by name, I came up with two solutions:

First, find the parent by name using anytrees find_by_attr

from anytree import Node, RenderTree, find_by_attr

with open('input.txt', 'r') as f:
    lines = f.readlines()[1:]
    root = Node(lines[0].split(" ")[0])

    for line in lines:
        line = line.split(" ")
        Node("".join(line[1:]).strip(), parent=find_by_attr(root, line[0]))

    for pre, _, node in RenderTree(root):
        print("%s%s" % (pre, node.name))

Second, just cache them in a dict while we create them:

from anytree import Node, RenderTree, find_by_attr

with open('input.txt', 'r') as f:
    lines = f.readlines()[1:]
    root = Node(lines[0].split(" ")[0])
    nodes = {}
    nodes[root.name] = root

    for line in lines:
        line = line.split(" ")
        name = "".join(line[1:]).strip()
        nodes[name] = Node(name, parent=nodes[line[0]])

    for pre, _, node in RenderTree(root):
        print("%s%s" % (pre, node.name))

input.txt

Parent Child
A      A1
A      A2
A2     A21

Output:

A
├── A1
└── A2
    └── A21
Fabian N.
  • 3,807
  • 2
  • 23
  • 46
  • 1
    Hi @Fabian N would you mind adding the input.txt file you are working with? I think your answer could help me but am not sure without seeing the input. What do you mean with "get a reference to the parent by name" ? Anytree has export/import methods, will give you precisely the root node, _but just that_ If you can please provide input.txt, and, also check my question https://stackoverflow.com/questions/51903732/exporting-importing-trees-created-with-python-anytree-2-4-3-library thank you very much – gaurwraith Aug 18 '18 at 12:12
  • N Guess you are working directly with the Output as input.txt? There's got to be a simpler way ! – gaurwraith Aug 18 '18 at 12:14
  • 1
    @gaurwraith I just copied the ops example into a file and called it `input.txt`. You are right, I tried first with anytrees importers but the code to transform the ops input into something one of anytrees importers would understand (json, dict or indent based) turned out to be much longer than simply implementing it directly – Fabian N. Aug 18 '18 at 12:16
  • Hi Fabian, Can you please help me with this https://docs.google.com/document/d/1O2ETX3vWGgSak0GZp4XBAamFWKZEbMkXlH5jIV4uyxU/edit?usp=sharing ? I am stuck for more than 4 hours now. Thanks – user3156040 Dec 17 '20 at 20:14
  • Hey @Fabian N. can you help me with this one? https://stackoverflow.com/questions/74622229/renaming-anytree-parent-and-child-name – Abdullah Al Mamun Nov 30 '22 at 02:27