Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Hash of Arrays of Hashes Parsing

by SmokeyB (Scribe)
on Sep 17, 2003 at 19:29 UTC ( [id://292236]=perlquestion: print w/replies, xml ) Need Help??

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

Hey All!

I have this hash:
my %foo = ( Info => [ { MakeEng => 1, MakeFre => 2, ModelEng => 3, ModelFre => 4, ModelYear => 5, }, { MakeEng => 6, MakeFre => 7, ModelEng => 8, ModelFre => 9, ModelYear => 0, }, ], VIN => { VINStatus => 'active', VechileDT => 'on', }, );
I want to parse through in and turn each main heading (Info,VIN) into tables with the next level keys will be the table fields.

I was going to use a foreach loop, but how can I tell the data is from an array or a hash??

Please help!

Replies are listed 'Best First'.
Re: Hash of Arrays of Hashes Parsing
by tcf22 (Priest) on Sep 17, 2003 at 19:47 UTC
    Try this:
    if(ref($reference) eq 'HASH'){ print 'Its a HASH reference'; ## Do Hash processing }elsif(ref($reference) eq 'ARRAY'){ print 'Its an ARRAY reference'; ## Do array processing }elsif(ref($reference)){ print 'Its a ' . ref($reference) . ' reference'; ## Handle invalid reference }else{ print "It isn't a reference"; ## Actual value, not a reference - do something }

    - Tom

      Thanks Tom!

      That was perfect.

      Cheers!
Re: Hash of Arrays of Hashes Parsing
by gryphon (Abbot) on Sep 17, 2003 at 20:24 UTC

    Greetings SmokeyB,

    I was bored (and I think I'm coming down with a fever, so coding is always fun) so I coded up some stuff for you. It's not good code, but it may help you get in the direction you're looking for. I made the assumption that "into tables" means "into HTML tables".

    #!/usr/bin/perl use strict; use warnings; my %foo = ( Info => [ { MakeEng => 1, MakeFre => 2, ModelEng => 3, ModelFre => 4, ModelYear => 5, }, { MakeEng => 6, MakeFre => 7, ModelEng => 8, ModelFre => 9, ModelYear => 0, }, ], VIN => { VINStatus => 'active', VechileDT => 'on', }, ); foreach my $table (keys %foo) { print '<h3>', $table, '</h3>', "\n"; print "<table>\n"; if (ref $foo{$table} eq 'HASH') { print '<tr><td>', $_, '</td><td>', $foo{$table}{$_}, "</td></tr>\n +" foreach (keys %{$foo{$table}}); } elsif (ref $foo{$table} eq 'ARRAY') { print '<tr>'; print '<td>', $_, '</td>' foreach (keys %{$foo{$table}[0]}); print "<tr>\n"; foreach my $row (@{$foo{$table}}) { print '<tr>'; print '<td>', $_, '</td>' foreach (values %{$row}); print "<tr>\n"; } } else { print "<tr><td>Badness. Something unexpected in %foo</td></tr>\n"; } print "</table>\n\n"; } exit;

    I don't know the extent of your project, but if you're looking for something long-term that's going to map into some kind of web reporting thing, you should definately take a look at HTML::Template. Using that, you could just muck around a little with your %foo and then just pass that into a template. Magic then happens.

    gryphon
    code('Perl') || die;

Re: Hash of Arrays of Hashes Parsing
by hmerrill (Friar) on Sep 17, 2003 at 20:37 UTC
    How about
    foreach my $key (keys %foo) { if ($key eq "Info") { print "I'm working with the Info array\n"; print "Table name is 'Info'\n"; ### each element of the Info array is a hash reference ### foreach my $info_hashref (@{$foo{'Info'}}) { while (my ($k, $v) = each %$info_hashref) { print "column name is $k, value is $v\n"; } } } else: print "Table name is 'VIN'\n"; while (my ($k, $v) = each %{$foo{'VIN'}}) { print "column name is $k, value is $v\n"; } } }
    Careful 'cause this is completely untested.

    HTH.
      Hey hmerrill,

      Thank-you, that would work fine, but it's very specific. The hash itself can be populated with a wide variety of keys and data, never really know exactly what will be returned at the time.

      What I ended up doing is the following:
      print "\t<tr>\n"; if (ref($data) eq 'ARRAY') { foreach my $array (@$data) { foreach my $value (keys %$array) { print "\t\t<td>$array->{$value}</td>\n"; } } } elsif ref($data) eq 'HASH') { foreach my $value (keys %$data) { print "\t\t<td>$data->{$value}</td>\n"; } } else { print "\t\t<td>Too Bad Sucka!</td>\n"; } print "\t</tr>\n";
      Cheers!
        Your solution looks fine, but I have to comment on one thing - the naming of your variables. This is just personal preference, but IMHO it makes your code much clearer and much more readable if you name the variables - especially references - what they are, or what they contain.

        Here is your example with some of the variables renamed:
        print "\t<tr>\n"; if (ref($data) eq 'ARRAY') { ### Since each element of the array is a hash reference, ### name it so you know what it is. #foreach my $array (@$data) foreach my $hashref (@$data) { #foreach my $value (keys %$array) foreach my($key,$value) (each %$hashref) { #print "\t\t<td>$array->{$value}</td>\n"; print "\t\t<td>$value</td>\n"; } } } elsif ref($data) eq 'HASH') { #foreach my $value (keys %$data) foreach my($key,$value) (each %$data) { #print "\t\t<td>$array->{$value}</td>\n"; print "\t\t<td>$value</td>\n"; } } else { print "\t\t<td>Too Bad Sucka!</td>\n"; } print "\t</tr>\n";
Re: Hash of Arrays of Hashes Parsing
by hardburn (Abbot) on Sep 17, 2003 at 19:35 UTC

    ref

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2024-04-25 06:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found