faqts : Computers : Programming : Languages : Python : Snippets : Trees

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

17 of 22 people (77%) answered Yes
Recently 7 of 10 people (70%) answered Yes

Entry

Multi-node tree

Jul 5th, 2000 10:01
Nathan Wallace, unknown unknown, Hans Nowak, Snippet 217, Python Snippet Support Team


"""
Packages: new_datatypes.trees
"""
""" multitree.py
    Defines a tree class. With this tree it's easy to add, change and delete
    multiple elements per node. A node consists of a title (a string) and a
    list, which can be manipulated at will. Printing and foreach-functions
    are available.
    23 Dec 98   Creation.
    25 Dec 98   Added _printtree, elements, nodes.
"""
def _printtree(node, prefix=""):
    """ Helper print routine, called by MultiTreeNode.printtree(). """
    if prefix == "": print "|"
    for i in range(len(node.list)):
        if isinstance(node.list[i], MultiTreeNode):
            if i == len(node.list)-1:
                newprefix = prefix + "     "
            else:
                newprefix = prefix + "|    "
            print "%s+--- %s" % (prefix, str(node.list[i].title))
            if node.list[i].list != []:
                # we don't want a dangling |
                print "%s|" % (newprefix)
                _printtree(node.list[i], newprefix)
            print "%s" % (newprefix)
        else:
            print "%s+--- %s" % (prefix, str(node.list[i]))
class MultiTreeNode:
    class __TreePrintOptions:
        foo = 1
        bar = 2
        # I'll implement this later... maybe... :) User should be able to
        # provide his own print options.
    def __init__(self, title="<>", list=[]):
        self.title = title
        self.list = list
        self.printoptions = self.__class__.__TreePrintOptions()
    def __getitem__(self, index):
        return self.list[index]
    def __setitem__(self, index, value):
        self.list[index] = value
    def __repr__(self):
        str = "MultiTreeNode %s %s" % (self.title, self.list)
        return str
    def printtree(self):
        _printtree(self)
    def foreach(self, f):
        """ Do something with each element in the tree. f is a function that
            takes an element, does something with it, and returns a new value.
        """
        for i in range(len(self.list)):
            if isinstance(self.list[i], MultiTreeNode):
                self.list[i].foreach(f)
            else:
                # do something
                self.list[i] = f(self.list[i])
    def foreachnode(self, f):
        """ Do something with each *Node* we encounter. f is a different
            function than the f in foreach... this one should not return
            anything, rather it should do something with the node. 
        """
        for i in range(len(self.list)):
            if isinstance(self.list[i], MultiTreeNode):
                f(self.list[i])
                self.list[i].foreachnode(f)
            else:
                pass
    def elements(self):
        """ Returns the number of elements, *not* counting nodes. """
        global counter
        counter = 0
        def count(elem):
            global counter
            counter = counter + 1
        self.foreach(count)
        return counter
    def nodes(self):
        """ Returns the number of nodes. Does not count itself. """
        global counter
        counter = 0
        def count(node):
            global counter
            counter = counter + 1
        self.foreachnode(count)
        return counter            
MultiTree = MultiTreeNode   # alias
if __name__ == "__main__":
    MN = MultiTreeNode
    animals = MN("Animals", [
        MN("Mammals", [
            MN("Carnivores", [
                MN("Canines", ["Dog", "Wolf", "Jackal", "Fox"]),
                MN("Felines", ["Lion", "Tiger", "Leopard"]),
            ]),
            MN("Herbivores", ["Sheep", "Goat"]),
        ]),
        MN("Birds", []),
        MN("Reptiles", []),
        MN("Insects", []),
        MN("Amphibians", []),
        MN("Fish", ["Shrimp", "Goldfish", "Shark"]),
    ])
    def _test1():
        print animals[0]    # print Mammals
        animals.printtree()
    def _test2():
        def f(elem):
            return elem + " sucks!"
        print "for‘ach:"
        animals.foreach(f)
        print animals
    def _test3():
        def g(node):
            node.title = node.title + " suck donkey!"
        print "foreachnode:"
        animals.foreachnode(g)
        print animals
    # put test here...
    # _test1()
    print animals.elements(), animals.nodes()