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

Hi Monks,

I haven't dared tread this hallowed ground before now, but looking at some of the other questions, it looks like apprentices like me are welcome. In any case, I have a problem understanding referencing and dereferencing (well, i think that's my problem). Here is my code:

#!/ms/dist/perl5/bin/perl5.8 # Standard module imports use Data::Dumper; use strict; use warnings; my $hashArrayRef; $hashArrayRef = [{ 'dateOfBirh' => '22 March 1971', 'firstName' => 'Ronnie', 'lastName' => 'Smith' }, { 'timeNow' => '14 April 1972', 'firstName' => 'Claudia', 'lastName' => 'Winkleman' }]; print Dumper(\$hashArrayRef); print "\n"; my @deRefHashArray = @$hashArrayRef; print Dumper(@deRefHashArray); print "\n"; print scalar @deRefHashArray; print "\n"; my %resultHash; my $countResult = $#deRefHashArray; print $countResult; print "\n"; for (my $counter = 0; $counter < $countResult; $counter++) { %resultHash = {$deRefHashArray[$counter]}; while ( my ($key, $value) = each(%resultHash) ) { print "$key => $value\n"; } } 1;

And here's the ouput:

$VAR1 = \[ { 'firstName' => 'Ronnie', 'dateOfBirh' => '22 March 1971', 'lastName' => 'Smith' }, { 'firstName' => 'Claudia', 'timeNow' => '14 April 1972', 'lastName' => 'Winkleman' } ]; $VAR1 = { 'firstName' => 'Ronnie', 'dateOfBirh' => '22 March 1971', 'lastName' => 'Smith' }; $VAR2 = { 'firstName' => 'Claudia', 'timeNow' => '14 April 1972', 'lastName' => 'Winkleman' }; 2 1 Odd number of elements in anonymous hash at arrayTest_monk.pl line 38. Reference found where even-sized list expected at arrayTest_monk.pl li +ne 38. Use of uninitialized value in concatenation (.) or string at arrayTest +_monk.pl line 40. HASH(0x82007a4) =>

Essentially, I have an array of hashes that is referenced. I want to iterate over the array, and then access the hash inside each of the elements - even in my example just to iterate over them too and print out the results. The problem comes in accessing the hashes - I can't grasp what I need to do to persuade my program that the element in the array is a hash, and therefore let me access it...

I know this post is long, but hopefully there's enough info to see what I'm strugggling with.

Many thanks.

Replies are listed 'Best First'.
Re: arrays, hashes, dereferencing confusion - need help
by Corion (Patriarch) on Mar 20, 2010 at 09:50 UTC

    When Perl tells you a line number in an error, it often helps to look at that line:

    Odd number of elements in anonymous hash at arrayTest_monk.pl line 38.
    %resultHash = {$deRefHashArray[$counter]};

    To me it seems as if you wanted to write

    %resultHash = <b>%</b>{$deRefHashArray[$counter]};
      I did look at the line - I just didn't know what to do about what it said!

      Easy when you know how, eh?

      Thanks!

        Its also easy when you don't know :)

        perl -Mdiagnostics -le "my %foo = 1 "

        Odd number of elements in hash assignment at -e line 1 (#1)
        (W misc) You specified an odd number of elements to initialize a hash, which is odd, because hashes come in key/value pairs.
Re: arrays, hashes, dereferencing confusion - need help
by Marshall (Canon) on Mar 20, 2010 at 17:19 UTC
    Also, 'C' style for loops are seldom needed in Perl. Another way to formulate what I think you want...
    #!/ms/dist/perl5/bin/perl5.8 # Standard module imports use Data::Dumper; use strict; use warnings; my $hashArrayRef; $hashArrayRef = [{ 'dateOfBirh' => '22 March 1971', 'firstName' => 'Ronnie', 'lastName' => 'Smith' }, { 'timeNow' => '14 April 1972', 'firstName' => 'Claudia', 'lastName' => 'Winkleman' }]; print Dumper($hashArrayRef); #no need for \$hashArrayRef print "\n"; foreach my $href (@$hashArrayRef) { foreach my $key (keys %$href) { print "$key \t$href->{$key}\n"; } print "\n"; } __END__ prints: $VAR1 = [ { 'firstName' => 'Ronnie', 'dateOfBirh' => '22 March 1971', 'lastName' => 'Smith' }, { 'firstName' => 'Claudia', 'timeNow' => '14 April 1972', 'lastName' => 'Winkleman' } ]; firstName Ronnie dateOfBirh 22 March 1971 lastName Smith firstName Claudia timeNow 14 April 1972 lastName Winkleman
Re: arrays, hashes, dereferencing confusion - need help
by biohisham (Priest) on Mar 20, 2010 at 18:32 UTC

    kudos for "use strict" and "use warnings"

    Understanding the error message can give clues as to what could the matter be...
    "Reference found where even-sized list expected at arrayTest_monk.pl line 38."

    is a warning that tells you that perl is trying to make a hash out of a passed list, and since hashes are associative (they have key/value pairs) hence for the set to be complete an even-sized list has to be passed so that each key would have its associated value..That wouldn't be detectable were you not invoking warnings! consider the following:

    use strict; use warnings; my @keyVal1 =qw(something 1 another 2); my @keyVal2 = qw(SOMETHING 1 ANOTHER); my %hash1 = @keyVal1; my %hash2 = @keyVal2; use Data::Dumper; print Dumper(\%hash1); print "\n"; print Dumper(\%hash2);

    Since each member of @deRefHashArray is a hash then inspecting the warnings would show you that you haven't dereferenced it appropriately..

    have been of great benefit to me and so wish they would be to you too..

    Here's your code after minor touches to get you started
    #!/usr/local/bin/perl use Data::Dumper; use strict; use warnings; my $hashArrayRef; $hashArrayRef = [{ 'dateOfBirh' => '22 March 1971', 'firstName' => 'Ronnie', 'lastName' => 'Smith' }, { 'timeNow' => '14 April 1972', 'firstName' => 'Claudia', 'lastName' => 'Winkleman' }]; print Dumper(\@$hashArrayRef); #Properly dereferenced..compare output print "\n"; print Dumper(@$hashArrayRef); print "\n"; for (my $counter = 0; $counter <= $#$hashArrayRef; $counter++) { while ( my ($key, $value) = each(%{@$hashArrayRef[$counter]}) +) { print "$key => $value\n"; } }
    wish you a nice Perl journey...


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.