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

I am trying to loop over each array element with nested loop over the hash keys in each element

for (my $i = 0; $i < 3; $i++) { # array has 3 elements foreach my $key (keys @{$AoH[$i]}) { # DO STH } }

But I get a warning "Not an ARRAY reference" ...what am I doing wrong? Example data:

@AoH = ( { a => "a1", b => "b1", c => "c1", }, { d => "d1", e => "e1", f => "f1", }, { g => "g1", h => "h1", i => "i1", }, );

So I want to access a, b & c at level $AoH[0], then d, e & f at $AoH1 etc.

Replies are listed 'Best First'.
Re: Dereferencing array of hashes
by LanX (Saint) on Nov 11, 2013 at 18:46 UTC
    Dereference with % not @.

    update

    Maybe better written as:

     do_something for map { keys %$_ } @AoH;

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: Dereferencing array of hashes
by toolic (Bishop) on Nov 11, 2013 at 18:59 UTC
    perldsc
    use warnings; use strict; my @AoH = ( { a => "a1", b => "b1", c => "c1", }, { d => "d1", e => "e1", f => "f1", }, { g => "g1", h => "h1", i => "i1", }, ); for my $i (0 .. $#AoH) { for my $key (keys %{ $AoH[$i] }) { print "$i $key\n"; } }
Re: Dereferencing array of hashes
by Kenosis (Priest) on Nov 11, 2013 at 18:59 UTC

    Building upon LanX's reply, perhaps the following will be helpful. Also note that it's not necessary to use a C-style loop here:

    use strict; use warnings; my @AoH = ( { a => "a1", b => "b1", c => "c1", }, { d => "d1", e => "e1", f => "f1", }, { g => "g1", h => "h1", i => "i1", }, ); for my $i ( 0 .. $#AoH ) { for my $key ( keys %{ $AoH[$i] } ) { print "$key => $AoH[$i]{$key}\n"; } print "\n"; }

    Output:

    c => c1 a => a1 b => b1 e => e1 d => d1 f => f1 h => h1 g => g1 i => i1
      ...it's not necessary to use a C-style loop here

      Indeed. In fact I'd simplify things even further by not using an array index at all:

      for my $item ( @AoH ) { for my $key ( keys %$item ) { print "$key => $item->{ $key }\n"; } }

        Oh, this is smart++! Am glad you added this comment!

Re: Dereferencing array of hashes
by Laurent_R (Canon) on Nov 11, 2013 at 19:57 UTC

    Also note that it's not necessary to use a C-style loop...

    Yes, sure, but you don't even need a $i variable to loop on the array and make a real Perl loop using directly the reference. This makes the dereferencing simpler.

    use strict; use warnings; my @AoH = ( { a => "a1", b => "b1", c => "c1", }, { d => "d1", e => "e1", f => "f1", }, { g => "g1", h => "h1", i => "i1", }, ); for my $hashref (@AoH) { print "$_ => $$hashref{$_}\n" for (keys %$hashref); }
    which will print:
    $ perl aoh.pl c => c1 a => a1 b => b1 e => e1 d => d1 f => f1 h => h1 g => g1 i => i1

      monkini: The critical thing to remember here is that a so-called "array of hashes" (an @AoH) is actually an array of hash references, i.e., every element is already a hash reference. You may as well use those references as such in a Perl-style for-loop as shown by Laurent_R (although I would have used the arrow de-referencing notation  $hashref->{$_} instead of the  $$hashref{$_} form).

        (although I would have used the arrow de-referencing notation $hashref->{$_} instead of the $$hashref{$_} form)

        Yes, right, that's actually what I would probably do also given the time. I typed my post in a rush before leaving for something else and used the dereferencing notation I still know best, but I have been trying in the last months to use more and more the arrow dereferencing notation, which is somewhat clearer. I am now using systematically the arrow notation for code refs and am trying to do it more and more for hash or array refs.