[Tutor] depth first with a twist
Magnus Lycka
magnus@thinkware.se
Sun Mar 2 20:29:02 2003
At Sun, 2 Mar 2003 11:41:44 -0500, Poor Yorick wrote:
>Hi, I majored in a social science, so I'm hoping this group can help me
>fill in the gaps;)
Sure.
>I have a dictionary where each key contains a list of
>values. Values 1 and 2 are parent, and older_sibling, respectively. I
>would like to append an order number onto each list, using parent and
>older_sibling to determine the order, and am looking for an iterative
>solution. I have written a function which works, but boy, is it ugly!
Ok. Maybe this indicates that you need a different abstraction.
> def OrderDepth(self):
I see that this is a method (due to indentation, and "self"), but the fact
that you don't use "self" a single time in the code suggests that the code
is in fact in the wrong class! Methods should work with the attributes of
the instance of the class! May I suggest having a look at Arthur Riel's
book "Object-Oriented Design Heuristics".
In this case I think the logic should be in a Tree Item class. Below,
I instanciate it from your dict, but it might be unwarranted to use
both represetations in practice. As I see it, each parent object should
be able to sort out his children, and then it's fairly trivial. I don't
know if this is fewer lines of code than your version, but it makes
more sense to me. Each method is fairly trivial.
I didn't include the number before the printed item, but that's a
trivial addition. E.g. instead of a print statement in "printTree"
there could be an append to a list (either known by name or passed
as argument), and then it's trivial to iterate the list and print
with a number before each line. It's also possible to pass an
object that returns an incremented number on each access, to printTree.
# A registry of items in the tree, might not be global in "real" code.
reg = {}
class TreeItem:
def __init__(self, name, parent, older_sibling, note):
self.name = name
self.parent = parent
self.older_sibling = older_sibling
self.note = note
self.children = []
# Register myself by name, so my children will find me.
reg[name] = self
def tellParent(self):
# Hi daddy, I'm your kid
if self.parent:
try:
reg[self.parent].addChild(self)
except KeyError:
print self.name, "is missing his parent", self.parent
raise
def addChild(self, child):
# Oops, this one claims to be my kid. ;)
self.children.append(child)
def printTree(self):
# First me, then my kids (and their kids) in order
print self
self.sortChildren()
for child in self.children:
child.printTree()
def sortChildren(self):
lastChild = None
sorted = []
while self.children:
for child in self.children:
if child.older_sibling == lastChild:
self.children.remove(child)
sorted.append(child)
lastChild = child.name
break
else:
# Error handling, we don't expect to get here
print "Bad child list"
print "Sorted", map(str, sorted)
print "Leftovers", map(str, self.children)
raise SystemExit
self.children = sorted
def __str__(self):
return self.name
d = {'monty': [None, None, "Monty Python's Flying Circus"],
'actors': ['monty', None, 'Actor Data'],
'sketches': ['monty', 'actors', 'Sketch Data'],
'basic': ['actors', None, 'Basic Bio'],
'filmography': ['actors', 'basic', 'Filmography']}
for name, (parent, older, note) in d.items():
TreeItem(name, parent, older, note) # Self-registering...
# Once all items are registered we can inform parents of their
# chldren.
for item in reg.values():
item.tellParent()
# Find root item(s) and print tree(s)
for item in reg.values():
if item.parent is None:
# Root item!
item.printTree()
This should print:
monty
actors
basic
filmography
sketches
If you want the number before, write an incrementor class
like this:
class Incr:
def __init__(self):
self.x = 0
def get(self):
self.x += 1
return self.x
and modify one method:
def printTree(self, incr = Incr()):
print incr.get(), self
self.sortChildren()
for child in self.children:
child.printTree(incr)
Then it should come out like:
1 monty
2 actors
3 basic
4 filmography
5 sketches
--
Magnus Lycka, Thinkware AB
Alvans vag 99, SE-907 50 UMEA, SWEDEN
phone: int+46 70 582 80 65, fax: int+46 70 612 80 65
http://www.thinkware.se/ mailto:magnus@thinkware.se