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

- Is it cool to populate a hash of arrays with qq or qw?
e.g. my %animals = ( pets => [ qw(cat dog) ], non => [ qq(rhino giraffe) ], );
- If one of those is correct what goes in the blank if I want to iterate through one of the arrays?
foreach $i (???) { push ( @some_animals, $animals{pets}[$i] ); }

Replies are listed 'Best First'.
Re: Hash of Arrays (populating and iterating)
by pc88mxer (Vicar) on Mar 06, 2008 at 01:37 UTC
    It's not only cool, it's way cool to use qq and qw to populate HoA's.

    For your iteration question, try:

    foreach $i (0..$#{$animals{pets}}) { ... }
      Or this way -- why bother with indexes at all?
      foreach $animal ( @{ $animals{pets} } ) { push ( @some_animals, $animal ); }


      Nobody says perl looks like line-noise any more
      kids today don't know what line-noise IS ...
        That's true. I tried it that way at first and got unexpected results (the array getting treated as 1 item when I tried to sort and make the elements unique) but it's probably because I was using qq incorrectly to populate the hash in the first place. I should have used qw and the elements would have been separate elements.
      Awesome, that's the ticket. THANKS!

      Hi pc88mxer,

      This might be a silly question pardon me for that, but i will go ahead and ask this to you,what does $# do in the below code ?

      foreach $i (0..$#{$animals{pets}}) { ... }

        From perldata:

        The length of an array is a scalar value. You may find the length of array @days by evaluating $#days, as in csh. However, this isn't the length of the array; it's the subscript of the last element, which is a different value since there is ordinarily a 0th element.

        The syntax $#{ ... } extends this idea: it interprets whatever expression is between the braces as an array reference; dereferences it to get an array; and returns the subscript of the last element. For example:

        #! perl use strict; use warnings; my %animals = ( pets => [ qw( cat dog hamster ) ], non => [ qw( rhino giraffe ) ], ); for my $i (0 .. $#{ $animals{pets} }) { print "$i: ", $animals{pets}->[$i], "\n"; }

        Output:

        1:43 >perl 857_SoPW.pl 0: cat 1: dog 2: hamster 1:43 >

        But note that, as Cody Pendant says above, it’s generally better (where possible) to dispense with array indexes altogether.

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,