Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

(cLive ;-) Re: representing a tree graphically...

by cLive ;-) (Prior)
on Jan 09, 2002 at 04:00 UTC ( [id://137316]=note: print w/replies, xml ) Need Help??


in reply to Re: representing a tree graphically...
in thread representing a tree graphically...

They already are in a HoH structure
$page->[$id]->{'parent'} = whatever..
The 'treepath' element is just there to make sorting them a lot easier.

Since it's 'trivial' to render, perhaps you could provide an example? That would really help! Oh, and although I didn't specifiy, the graphical representation is for a web page.

thanks

cLive ;-)

Replies are listed 'Best First'.
Re: (cLive ;-) Re: representing a tree graphically...
by hossman (Prior) on Jan 09, 2002 at 11:57 UTC
    Okay, a couple of things...

    1. I don't really understand your example of "$page->[$id]->{'parent'}". I don't see how that's a hash of hashes.

    2. I underestimated the problem, because of the "|" issue. When I've seen this problem before, the only important issues were:
      1. Nest/tab the children properly
      2. Do something special for hte first/last child
      An example of "pipeless" output is in the method "render_node_nopipe" below

    3. Even with the pipes, I still think it's cleaner to use a recursive method -- BUT, instead of passing an "indent" depth, you pass an acctuall padding string, that contains the pipes. The only real new complexity is that when dealing with each node, it's not enough to know if that node is the last of it's siblings, you also have to know if it's parent was the last of it's siblings (in order to build up the padding string properly).
      An example of the recursive solution is the method "render_node" below.

    4. It should be clear how to make this generate the appropriate HTML (<img src..>) output by modifing the single letter vars.

    #!/usr/local/bin/perl -w use strict; my $d = " #"; my $t = " +"; my $l = " \\"; my $p = " |"; my $s = " "; my $tree = { 'one' => { 'two' => { 'five' => { 'boo' => { 'baz' => { }, }, }, }, 'three' => { 'four' => { }, 'yak' => { }, 'six' => { 'foo' => { 'yuk' => { }, }, 'ggg' => { }, }, }, }, }; print "with pipes...\n" . &render_node($tree->{'one'}, 'one'); print "no pipes...\n" . &render_node_tab($tree->{'one'}, 'one'); sub render_node { my ($tree, $node, $tok, $pad, $last) = @_; $tok = $s unless defined $tok; $pad = "" unless defined $pad; $last = 1 unless defined $last; my $out = $pad . $tok . $d . $node . "\n"; my @kids = sort keys %{$tree}; for (my $i = 0; $i < scalar @kids; $i++) { my $knode = $kids[$i]; my $ktree = $tree->{$knode}; my $klast = ($i+1 == scalar @kids); my $ktok = ($klast ? $l : $t); my $kpad = $pad . ($last ? $s : $p); $out .= &render_node($ktree, $knode, $ktok, $kpad, $klast); } return $out; } sub render_node_tab { my ($tree, $node, $tok, $indent) = @_; $tok = $s unless defined $tok; $indent = 0 unless defined $indent; my $out = ($s x $indent) . $tok . $d . $node . "\n"; my @kids = sort keys %{$tree}; for (my $i = 0; $i < scalar @kids; $i++) { my $knode = $kids[$i]; my $ktree = $tree->{$knode}; my $ktok = ($i+1 == scalar @kids) ? $l : $t; my $kindent = $indent+1; $out .= &render_node_tab($ktree, $knode, $ktok, $kindent); } return $out; } __END__ with pipes... #one + #three | + #four | + #six | | + #foo | | | \ #yuk | | \ #ggg | \ #yak \ #two \ #five \ #boo \ #baz no pipes... #one + #three + #four + #six + #foo \ #yuk \ #ggg \ #yak \ #two \ #five \ #boo \ #baz
      Re 1: Hash starts off as $page->{$id}-{'parent'}, but for readability's sake I created a second, ordered array of hashes that was the original IDs mapped to an array index showing the correct display order (ie, sorted by 'treepath'). It was just easier to visualise.

      Nice code, but one thing's not as it should be (which I implied, but didn't specify *explicitly* before). I need the nodes to display in order (to allow users to build the order they want pages displayed in when menus are drawn, so they need to be sorted by 'treepath', eg:

      #one + #two | \ #five | \ #boo | \ #baz \ #three + #four + #yak \ #six + #foo | \ #yuk \ #ggg
      and not the re-ordered way that your code outputs the tree at the moment, if that makes sense.

      But thanks for the insight. I'll have a little play with the ideas you presented.

      cLive ;-)

        i just used the stock "sort" but you could easily drop in any sort method, as long as the criteria for sorting was something htat could be looked up using the node name (or a property of hte node object if you used proper objects)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://137316]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-03-29 07:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found