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

Hi,

I know I'm doing something wrong, which makes me never able to print a proper value. I'm trying to pass a array of hashes to a subroutine.

my %hash; my @array; my $n = 1; $hash{"one$n") = "hi"; $n++; $hash{"one$n") = "hi 2 you too"; push @array, \%hash; my $n = 1; $hash{"two$n") = "hello"; $n++; $hash{"two$n") = "hello 2 you too"; push @array, \%hash; some_routine($n, \%some_other_hash, \@array); sub some_routine { #$n, and $h are other variables that may be passed to this routine. my ($n, $h, $array_of_hashes) = @_; foreach my $d (@{$array_of_hashes}) { print $d[0]{'one1'}; } #...also tried this... print $array_of_hashes[0]{'one1'}; print $array_of_hashes[0]{'one2'}; print $array_of_hashes[1]{'two1'}; print $array_of_hashes[1]{'two2'}; }
I basically used the above concept and never able to print accordingly. Usually just prints out stufff like "HASH(0xb5a3c)" etc.

What am I doing wrong? How can I pass an array of hashes to a subroutine and properly print out each hash keys/values stored inside the array?

Thanks,
Sylar

Replies are listed 'Best First'.
Re: Passing an array of hashes to a subroutine
by ikegami (Patriarch) on May 21, 2007 at 05:54 UTC

    Three problems.

    First, $d doesn't contain what you think it does, whatever that is.

    foreach my $d (@{$array_of_hashes}) { print $d[0]{'one1'}; }

    It contains the element at each index of the array (in turn). In other words, it contains a reference to a hash. Fix:

    foreach my $h (@{$array_of_hashes}) { print $h->{'one1'}; }

    Secondly, you reference the array @array_of_hashes even though no such array exists.

    print $array_of_hashes[0]{'one1'}; print $array_of_hashes[0]{'one2'}; print $array_of_hashes[1]{'two1'}; print $array_of_hashes[1]{'two2'};

    Had you used use strict as you should, you would have gotten an error. Fix:

    print $array_of_hashes->[0]{'one1'}; print $array_of_hashes->[0]{'one2'}; print $array_of_hashes->[1]{'two1'}; print $array_of_hashes->[1]{'two2'};

    See References Quick Reference.

    Finally, your array contains two references to the same hash.

    my %hash; my @array; ... push @array, \%hash; ... push @array, \%hash;

    Fix:

    my @array; { my %hash; ... push @array, \%hash; } { my %hash; ... push @array, \%hash; }

      Fix:

      my @array; { my %hash; ... push @array, \%hash; } { my %hash; ... push @array, \%hash; }

      Or:

      my @array; my %hash; # ... push @array, { %hash }; # ... push @array, { %hash };

        No, not quite. You would need to add something to clear the hash after it's pushed.

        my @array; my %hash; # ... push @array, { %hash }; %hash = (); # ... push @array, { %hash };

        But I don't like it. Since the natural progression is a loop, you've just advocated the following:

        my @array; my %hash; for (...) { %hash = (); # ... push @array, { %hash }; }

        I much prefer the following:

        my @array; for (...) { my %hash; # ... push @array, { %hash }; }
Re: Passing an array of hashes to a subroutine
by NetWallah (Canon) on May 21, 2007 at 05:59 UTC
    Data::Dumper is your friend.

    Your passing syntax is fine - you just need to understand that what you have passed is a reference to an array of Hash-refs.

    Your iteration "foreach my $d (@{$array_of_hashes})" aliases $d to a hashREF - which you need to de-reference.

    try

    print $d->{one1} ; # De-reference $d, then use the key "one1" to get t +he value

         "An undefined problem has an infinite number of solutions." - Robert A. Humphrey         "If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman

Re: Passing an array of hashes to a subroutine
by perleager (Pilgrim) on May 21, 2007 at 06:27 UTC
    Thank you guys. I got what I was trying to work on to work properly and they now print fine!

    Again, thanks for the further explanation on this subject.

    Very much appreciated,
    Sylar