anytree icon indicating copy to clipboard operation
anytree copied to clipboard

A way to create iterating labels when rendering tree

Open Vathys opened this issue 3 years ago • 2 comments

Is there a way to be able to create iterate inside a RenderTree? For example, I want to print a tree labeled 1, 2, 3,... before each child. I want to do this to be able to print a selectable menu commandline menu, but not necessarily changing the names of each child.

Vathys avatar Feb 01 '22 18:02 Vathys

With RenderTree, you can use the .by_attr() method to customise the representation of each node. To generate a numbering for the children, you could create a function that looks up the current node's index in its parent's tuple of children:

from anytree import Node, RenderTree

root = Node('root')
ch1 = Node('first child', parent=root)
ch2 = Node('second child', parent=root)
ch3 = Node('third child', parent=root)
ch2ch1 = Node('first child of second child', parent=ch2)
ch2ch2 = Node('second child of second child', parent=ch2)
ch2ch3 = Node('third child of second child', parent=ch2)

get_index = lambda n: n.parent.children.index(n)
print(RenderTree(root).by_attr(lambda n: f'{get_index(n)+1}. {n.name}'  if not n.is_root else n.name))

prints

root
├── 1. first child
├── 2. second child
│   ├── 1. first child of second child
│   ├── 2. second child of second child
│   └── 3. third child of second child
└── 3. third child

However if you want unique increasing numbers for each option to select from, regardless of the level, consider using a generator: (courtesy of https://stackoverflow.com/q/9604516)

import itertools

c=itertools.count()
print(RenderTree(root).by_attr(lambda n: f'{next(c)+1}. {n.name}'  if not n.is_root else n.name))

prints

root
├── 1. first child
├── 2. second child
│   ├── 3. first child of second child
│   ├── 4. second child of second child
│   └── 5. third child of second child
└── 6. third child

eckp avatar Feb 14 '22 22:02 eckp

@c0fec0de question answered, issue can be closed.

eckp avatar Dec 03 '23 19:12 eckp