In [1]:
"""
This is the common data stucture objects which may be usable
Part of the package of Alex's tools
Should be placed at <jupyter notebook root>/axtoools
__author__ = "Alex Xiao <http://www.alexxiao.me/>"
__date__ = "2017-02-08"
__version__ = "0.5"
"""
In [210]:
class Tree(object):
"""
Return the object the code carry
"""
def __call__(self):
return self.obj
"""
The Node of tree object
name: the name of the root
obj: the object assigned to the node
parent: the parent of the node, default to None for root
*NOTE: to add a child, please use add function rather than define parent here!
"""
def __init__(self,name,obj,parent=None):
self.name=name
self.obj=obj
self.parent = parent
if parent!=None and not parent.has(name):
#in case of the node has not been addded to parent
parent.children[name]=self
self.children=dict()
if parent==None:
self.level=0
else:
self.level=parent.level+1
"""
Return the list of the children
output:
[list] of all children
"""
def list(self):
if len(self.children)>0:
return list(self.children.keys())
"""
If the current node the root of the tree
"""
def is_root(self):
return self.parent==None
"""
If the current node the leaf of the tree (no child)
"""
def is_leaf(self):
rtn=True
if len(self.children)>0:
rtn=False
return rtn
"""
Remove one child
"""
def remove(self,name):
self.children.remove(name)
"""
Add one child
Input:
name: the name of the child
obj: the child, if the object is a tree, it all be hooked to current tree as a node
"""
def add(self,name,obj):
if type(obj)==type(self):
#adding a tree as object
obj.name=name
obj.hook(self)
else:
#self.children[name]=
Tree(name,obj,self)
"""
If the node has given child
"""
def has(self,name):
return name in self.children
"""
Get the child by name, None if not exist
"""
def child(self,name):
if name in self.children:
return self.children[name]
"""
The max depth from current node
"""
def depth(self):
dep=0
if len(self.children)>0:
for child in self.children:
cdep=self.children[child].depth()
if cdep>dep:
dep=cdep
dep+=1
return dep
"""
Cascade the level change to all children
"""
def __update_level(self,parentlevel):
self.level=parentlevel+1
if len(self.children)>0:
for child in self.children:
self.children[child].__update_level(self.level)
"""
Hook the current root node to a parent node of the other tree
"""
def hook(self, parent):
if self.parent==None and parent!=None and not parent.has(self.name):
#ok to hook
self.parent=parent
#in case of the node has not been addded to parent
parent.children[self.name]=self
self.__update_level(parent.level)
else:
if self.parent!=None:
raise ValueError('[Error] This is not root node, can not be hooked to the other parent!')
if parent==None:
raise ValueError('[Error] Cannot hook to the None parent!')
if parent.has(self.name) and parent.child(self.name)!=self:
raise ValueError('[Error] Cannot replace existing child of parent!')
def __repr__(self):
if self.parent==None:
out='['+self.name+']'
else:
out=''
length=15
for i in range(1,self.level):
out+=''.ljust(length,' ')
out+='('+str(self.level)+')'
out+=('['+self.name+']').rjust(length-1,'-')
if len(self.children)>0:
for child in self.children:
out+='\n'+self.children[child].__repr__()
return out
In [2]:
Out[2]: