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

Generating recursive hash

by Anonymous Monk
on Dec 12, 2009 at 04:44 UTC ( [id://812474]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have the following data structure :

id name parent 1 data 0 2 data 1 3 data 1 4 data 3 5 data 4

How can I make recursive hash out of this?

Replies are listed 'Best First'.
Re: Generating recursive hash
by GrandFather (Saint) on Dec 12, 2009 at 05:12 UTC

    To what end? What do you want to achieve using the data structure? What form is your "data structure" actually in? Are you sure you actually want a hash?


    True laziness is hard work

      unfortunately I cannot tell to what end, it might be 3 levels deep or more so I don't want to hard code it.

      I actually have these info in a mysql db, what I would want to do is pulling those data, build the hash so I can display them in a nicely formatted structure.

      root - first level -- second level --- third level - first

      and so on, I am using Template Toolkit and I figured out that I can display it this way using "VIEWS" but I have no idea how to sort up this mess.

      Note that both the 'id' & 'name' fields are important (the name so a user can understand what this section is and the ID for editing it)

        I know nothing about TT and having glanced at the documentation I really don't want to get up to speed with it for this exercise. However the following may get you headed in a useful direction:

        use strict; use warnings; use DBI; my $tmpFileName = 'temp'; open my $outFile, '>', $tmpFileName or die "Can't open $tmpFileName: $ +!\n"; print $outFile $_ for <DATA>; close $outFile; my $dbh = DBI->connect ("DBI:CSV:") or die "DBI connect failed: $DBI::errstr"; my $sth = $dbh->prepare ("SELECT * FROM temp"); my @structure; my %idMap; $sth->execute (); while (my $row = $sth->fetchrow_hashref) { my ($id, $name, $parent) = @{$row}{'id', 'name', 'parent'}; if (! $parent) { push @structure, {id => $id, name => $name, children => []}; $idMap{$id} = $structure[-1]; next; } if (exists $idMap{$parent}) { push @{$idMap{$parent}{children}}, {id => $id, name => $name, +children => []}; $idMap{$id} = $idMap{$parent}{children}[-1]; next; } die "Can't handle children id provided before parent"; } $sth->finish (); $dbh->disconnect (); print dumpChildren($_) for @structure; sub dumpChildren { my ($node, $indent) = @_; $indent ||= ''; my $str = "$indent$node->{name}\n"; $indent .= ' '; $str .= dumpChildren ($_, $indent) for @{$node->{children}}; return $str; } __DATA__ id,name,parent 1,data1,0 2,data2,1 3,data3,1 4,data4,3 5,data5,4

        Prints:

        data1 data2 data3 data4 data5

        True laziness is hard work
Re: Generating recursive hash
by roboticus (Chancellor) on Dec 12, 2009 at 08:39 UTC

    If you meant a different kind of recursive hash, you could try:

    #!/usr/bin/perl -w use strict; use warnings; use Data::Dumper; my (@child_list, %Nodes, $id, $data, $parent); while (<DATA>) { @{$Nodes{$id}}{'ID','Data','Parent'} = (($id,$data,$parent)=split +/\s+/,$_); $Nodes{$parent}{Children}{$id} = $Nodes{$id}; push @child_list, $id; } delete $Nodes{$_} for @child_list; print Dumper(\%Nodes); + __DATA__ 1 data 0 2 data 1 3 data 1 4 data 3 5 data 4

    ...roboticus

Re: Generating recursive hash
by bichonfrise74 (Vicar) on Dec 12, 2009 at 07:15 UTC
    Perhaps something like this?
    #!/usr/bin/perl use strict; my %record; while (<DATA>) { next if /^id/; my @a = split; $record{$a[2]}->{$a[0]} = $a[1]; } __DATA__ id name parent 1 data 0 2 data 1 3 data 1 4 data 3 5 data 4
Re: Generating recursive hash
by baxy77bax (Deacon) on Dec 12, 2009 at 10:20 UTC
    hi,

    well, GrandFather has a point! An alternative to what you are asking is to create a tree structure and then walk through it (it is more memory efficient then building hash of hashes). something like this:

    use strict; my %hash; while (<DATA>){ chomp; my @array = split(',',$_); my ($child, $parent) = ($2,$1); $hash{$array[1]} = [] unless (exists $hash{$array[1]}); push @{$hash{$array[1]}}, $array[0]; } #and now you do the Johnny Cash (walk the line) my @line; _Johnny(5); # entry that you wish to query foreach (@line){ print $_ . ","; } #------------------------------------------------# sub _Johnny { my $x = shift; push (@line,$x); for (@{$hash{$x}}){ _Johnny($_); } } #------------------------------------------------# __DATA__ 3,1 5,1 4,3 2,7 6,4 8,2 7,6 11,5 12,5 43,11 15,11
    but the question is

    What do you want to achieve using the data structure?

    cheers , baxy

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2024-03-28 11:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found