I built this Node class:
class Node:
"""
Node of Tree object:
"""
def __init__(self, data):
self.data = data
self.parent = None
self.children = list()
def __repr__(self) -> str:
return f"Node: {self.data}"
def set_data(self, data):
self.data = data
def get_data(self):
return self.data
def set_children(self, *children):
for child in children:
child.parent = self
assert isinstance(child, Node)
self.children.append(child)
def get_children(self):
return self.children
def set_parent(self, parent):
assert isinstance(parent, Node)
parent.set_children(self)
def get_parent(self):
return self.parent
def get_root(self):
if self.parent == None:
return self
p = self.get_parent()
while bool(p.get_parent()):
print(bool(p.get_parent()))
p = p.get_parent()
return p
def is_root(self):
if self.parent is None:
return True
return False
def is_leaf(self):
if self.children:
return False
return True
def get_level(self):
if self.is_root():
return 0
return 1 + self.parent.get_level()
def print_tree(self) -> None:
if self.parent:
spaces = "| " * self.get_level()
prefix = spaces + "|-- " if self.parent else ""
print(prefix + str(self.data))
if self.children:
for child in self.children:
child.print_tree()
The problem I am facing is, how can I create nodes and assign parents or child to them using loops? I've tryed this:
root = a = Node(0)
for i in range(1, 10):
new_node = Node(i)
a.set_children(new_node)
a = new_node
root.print_tree()
which works, printing:
0
| |-- 1
| | |-- 2
| | | |-- 3
| | | | |-- 4
| | | | | |-- 5
| | | | | | |-- 6
| | | | | | | |-- 7
| | | | | | | | |-- 8
| | | | | | | | | |-- 9
BUT, I need a way to make nodes subscriptable in such a way that if I need to assign more children to a previous node, like the node 4. I could go back to it and assign them.
Maybe building a separete class that would assign indexes to the nodes or something like it idk.
The data that I want to transform into a tree comes in a csv file and is like this:
AUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG02;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;FNS_1700 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_1701 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_3352 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_89069 (TS);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_80304 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_660 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80079 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80412 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_14118 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3008 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3007 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81391 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_17629 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_659 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_665 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81106 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;FNS_80996 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80080 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_4139 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_17634 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_80081 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_2738 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_86546 (RA);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_4704 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_663 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_656 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_17637 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3133 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3000 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_80082 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG01;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
You can use the following function:
def from_csv(csv):
parent = root = Node(None) # dummy node
curdepth = 0
for line in csv.splitlines():
depth = len(line) - len(line.lstrip(";"))
while curdepth > depth:
parent = parent.parent
curdepth -= 1
node = Node(line.strip(";"))
node.set_parent(parent)
parent = node
curdepth += 1
return root
Here is a demo run:
csv = """AUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG02;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;FNS_1700 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_1701 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_3352 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_89069 (TS);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_80304 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_660 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80079 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80412 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_14118 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3008 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3007 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81391 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_17629 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_659 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_665 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81106 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;FNS_80996 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80080 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_4139 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_17634 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_80081 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_2738 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_86546 (RA);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_4704 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_663 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_656 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_17637 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3133 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3000 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_80082 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG01;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
"""
root = from_csv(csv)
root.print_tree()
This outputs:
None
| |-- AUG
| | |-- AUG02
| | | |-- FNS_1700 (CD)
| | | | |-- FNS_1701 (CD)
| | | | | |-- FNS_3352 (FU)
| | | | | |-- FNS_89069 (TS)
| | | | | | |-- FNS_80304 (FU)
| | | | | | |-- FNS_660 (FU)
| | | | | | | |-- FNS_80079 (FU)
| | | | | | | |-- FNS_80412 (FU)
| | | | | | |-- FNS_14118 (FU)
| | | | | | |-- FNS_3008 (FU)
| | | | | | |-- FNS_3007 (FU)
| | | | | | | |-- FNS_81391 (FU)
| | | | | | |-- FNS_17629 (FU)
| | | | | |-- FNS_659 (FU)
| | | | | | |-- FNS_665 (FU)
| | | | | | | |-- FNS_81106 (FU)
| | | | | | | | |-- FNS_80996 (FU)
| | | | | | | |-- FNS_80080 (FU)
| | | | | | | |-- FNS_4139 (FU)
| | | | | |-- FNS_17634 (FU)
| | | | | |-- FNS_80081 (FU)
| | | | |-- FNS_2738 (CD)
| | | | |-- FNS_86546 (RA)
| | | | | |-- FNS_4704 (FU)
| | | | | |-- FNS_663 (FU)
| | | | | | |-- FNS_656 (FU)
| | | | |-- FNS_17637 (FU)
| | | | |-- FNS_3133 (FU)
| | | | |-- FNS_3000 (FU)
| | | | |-- FNS_80082 (FU)
| | |-- AUG01
This includes a root with value None
, because in theory it is possible that the CSV format defines multiple nodes at the top level, so it would represent a forest. The dummy root will then take those top level nodes as its children. If you expect only one top level node in the CSV input, then do:
root = from_csv(csv).get_children()[0]
root.parent = None
root.print_tree()