Let's say that I have a Python 3.6 list that looks like this:
l1 = [
[a,b,c],
[b,c],
[c],
[d, e],
[e]
...
]
I need to convert this to a tree-like structure using anytree, so that it looks like this:
>>> print(RenderTree(l1))
l1
|__ a
| |__b
| |__c
|___d
|__e
Consider the objects a
, b
, c
, d
, e
to be a string if that helps in any way. I've currently read a lot of the documentation for anytree and searched for a while on StackOverflow, but couldn't find anything that would help me resolve that issue. What's the most pythonic way I can resolve this issue?
Edit: To add clarification, the original list l1
is supposed to represent a tree, where the first element in l1
is the parent node, and each node inside it is a child node. Each child node can be a child node of the node before it, and so on
Edit Edit: So, here's what the original list would (hypothetically) look like:
l1 = [
['a', 'b', 'c'],
['b', 'c'],
['c'],
['d', 'e'],
['e']
]
Here, the first element for each sublist is always going to end up being a parent for that branch. Joining each of those branches together would result in me getting the format I need, but I've been struggling to put it into words (it's 2 am here). Here are some of my attempts:
For converting the list into nodes:
from anytree import Node
l = []
for x in l1:
a = Node(x[0])
for i in x[1:]:
Node(i, parent = a)
l.append(a)
However, this returns a tree/list so:
>>> l
[Node('/a'), Node('/b'), Node('/c'), Node('/d'), Node('/e')]
>>> print(RenderTree(l[0]))
Node('/a')
├── Node('/a/b')
└── Node('/a/c')
>>> print(RenderTree(l[1]))
Node('/b')
└── Node('/b/c')
>>> print(RenderTree(l[2]))
Node('/c')
>>> print(RenderTree(l[3]))
Node('/d')
└── Node('/d/e')
>>> print(RenderTree(l[4]))
Node('/e')
To filter this out, I tried to do the following:
def tuple_replace(tup, pos, val):
return tup[:pos] + (val,) + tup[pos+1:]
>>> l2=[]
>>> for pos, x in enumerate(l):
for pos_2, i in enumerate(x.children):
for j in l[pos+1:]:
if j.name == i.name:
x.children = tuple_replace(x.children, pos_2, i)
break
l2.append(x)
>>> for x in l2:
print(RenderTree(x))
Node('/a')
├── Node('/a/b')
└── Node('/a/c')
Node('/a')
├── Node('/a/b')
└── Node('/a/c')
Node('/b')
└── Node('/b/c')
Node('/d')
└── Node('/d/e')
That's the step that I'm currently at
Edit Edit edit:
So, the way the tree is represented is that I have a function that returns a list like l1
, and has the following logic behind it:
Each element in the list has 2 parts. The parent, and the children. The parent is the first element in the list, and everything else is its children, or it's children's children and so on. So an element like: [a, b, c]
and [d, e, f, g]
represents all the elements in the branch, not just the immediate parents that keep going down. That's where the rest of the elements come into play. The next element usually contains the parent's first child: [b, c]
and [e, f]
and [g]
. But now, the element [d, e, f, g]
is different from [a, b, c]
because there are 2 different sub-branches inside it instead of one. So, a tree such as this:
l1
|
|_a
| |__b
| |__c
|
|_d
|__e
| |__f
|__g
Would be described as:
Edit: fixed the input tree, because f
didn't have a stand alone branch
l1=[
[a,b,c],
[b, c],
[c],
[d,e,f,g],
[e,f]
[f]
[g]
]