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

Okay, I'm stumped. Someone tell me what I'm doing wrong here.
#!/usr/bin/perl -w # Make an array of hashes very explicitly. # This part works. @months = (); %m = ( full => "january", abbrev => "jan", number => 1, ); push @months, \%m; %m = ( full => "february", abbrev => "feb", number => 2, ); push @months, \%m; %m = ( full => "march", abbrev => "mar", number => 3, ); push @months, \%m; # etc # Now try to print it back out again. # This part doesn't work. while (<@months>) { print "$_->{full}\n"; print "$_->{abbrev}\n"; print "$_->{number}\n\n"; }
When I try this, I get empty lines instead of the contents of the hashes. Obviously I don't have the syntax quite right to do what I want. Any suggestions?

Replies are listed 'Best First'.
Re: Looping through an Array of Hashes
by trs80 (Priest) on Feb 21, 2002 at 23:39 UTC
    This could be rewritten as:
    #!/usr/bin/perl -w # Make an array of hashes. # This part works. use strict; # <- Note the use strict my @months = (); my %m = (); push @months, { full => "january", abbrev => "jan", number => 1, }; push @months, { full => "february", abbrev => "feb", number => 2, }; push @months, { full => "march", abbrev => "mar", number => 3, }; # etc # Now try to print it out. foreach my $month (@months) { print "$month->{full}\n"; print "$month->{abbrev}\n"; print "$month->{number}\n\n"; }
    This gets rid of the temp %m's you were creating as well and avoid the problem of the last reference wining, which is what you would have seen if you had changed the while to a foreach without changing the way you did your push.
    You should also check out CPAN for date modules that might save you some time.

    If you need to look at the contents of datastructure and not perform any action, that is verify content, you should look into using Data::Dumper, it would remove the need for the foreach and prints a nice tidy view of your data.
      very minor thing... u dont need to declare my %m = (); since its not being used anywhere...
      ++for your post, though :-)
Re: Looping through an Array of Hashes
by giulienk (Curate) on Feb 21, 2002 at 22:52 UTC
    You got a problem with <@months>, cause @months isn't a FILEHANDLE and it doesn't need <> around it. And of course you should switch from a while to a for loop. Still i doubt the code will do what i suppose you want it to do, cause you put in @months 3 references to the same hash %m.

    $|=$_='1g2i1u1l2i4e2n0k',map{print"\7",chop;select$,,$,,$,,$_/7}m{..}g

Re: Looping through an Array of Hashes
by Anonymous Monk on Apr 19, 2002 at 07:00 UTC
    is there a way to get it to work WITH the %m temp vars? for the life of me, i can't figure this out -- and it would save me a bunch of lines in a db pull i've got (i'm pulling the fields into a hash, stored in an array)
      I realize this is way too late to help this anon monk, but in case someone finds via search here's how you can do it with the temp hash...
      #!/usr/bin/perl use strict; use warnings; my %hash1 = ("a" => "Apple", "b" => "Ball"); my %hash2 = ("c" => "Cat", "d" => "Dog"); my @myarray; push @myarray, \%hash1; push @myarray, \%hash2; foreach my $value (@myarray) { foreach my $hvalue (keys %{$value}) { print $hvalue . "\t"; print $value->{$hvalue} . "\n"; } }