in reply to Nested Categories
This is a common pattern. The basic problem is "how to I generate a child pointer tree from a parent pointer representation (as would normally be stored in a DB)". The following is a (proven but not debugged) solution that doesnt require multiple queries, can handle the data in any order, and only requires a single forward pass over the data.
sub getCategories { my ($dbh)=@_; my $sql = qq~SELECT category_id, parent_id, category_name FROM ss_ +catalog_categories~; my $sth = $dbh->prepare($sql); $sth->execute; my %nodes; my @roots; my ($cid,$pid,$name); while ( ($cid,$pid,$name) = $sth->fetchrow_array()) { my $node=($nodes{$cid}||={}); $node->{name}=$name; $node->{pid}=$pid; $node->{cid}=$cid; if ($pid) { $nodes{$pid}{_kids}{$cid}=$node; } else { push @roots,$node; } } $sth->finish; return (\@roots,\%nodes); }
Roots contains the root nodes of your forest, and %nodes contains a hash keyed by the category id of the nodes. You can traverse each tree in the forest like this:
sub traverse { my ($node,$depth)=@_; $depth||=0; print " " x $depth,$node->{cid}," ",$node->{name},"\n"; foreach my $id ( sort {$a <=> $b} keys %{$node->{_kids}||{}} ) { traverse($node->{_kids}{$id},$depth+1); } } my ($r,$n)=getCategories($dbh); traverse($_) for sort { $a->{cid} <=> $b->{cid} } @$r;
For those that care the above code is a highly simplified form of what is used here for the Recently Active Threads.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Nested Categories (Aka: How to build a child pointer tree from a parent pointer representation)
by spaceout (Initiate) on Jan 03, 2005 at 19:52 UTC |