Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl How do I retrieve an array from a hash of arrays?

Tags:

perl

I'm fairly new to Perl, so forgive me if this seems like a simple question...

Anyway, I have a hash of arrays and I'm trying to retrieve one of the arrays in the hash, but all I can get is the scalar size of the array.

%HoA = a hash of arrays
$key = some key in the hash

foreach $nextItem (@HoA{$key}) {
  do a bunch of stuff with $nextItem
}

When I do this, $nextItem is always just the size of the array and the loop only runs through one time. I've tried printing the following:

@HoA{$key}
$HoA{$key}
@$HoA{$key}

The first two give me the scalar size and the third gives me nothing...what am I missing here?

UPDATE: I'm wondering if my problem is actually the way I'm adding the arrays to the hash. Here's what I'm doing:

@HoA{$key} = split(/ /, $list);

Does that stick the array in the hash, or the array size in the hash?

UPDATE 2: I tried the following block of code:

my $key = "TEST";
my %HoA = ();
my @testarray = (1, 2, 3);
@HoA{$key} = @testarray;
print Dumper(%HoA);

Here's the output:

$VAR1 = 'TEST';
$VAR2 = 1;

Why is it only sticking the first value of the array in?

like image 913
mrplainswalker Avatar asked Sep 21 '12 17:09

mrplainswalker


2 Answers

Try referencing your array this way:

%HoA = a hash of arrays
$key = some key in the hash

foreach $nextItem (@{$HoA{$key}}) {
  do a bunch of stuff with $nextItem
}

You take the array reference at $HoA{$key} and make it an array.

Edit: For your update, I think you will get what you want, if you do it this way:

@{$HoA{$key}} = split(/ /, $list);

or you can do

push(@{$HoA{$key}}, split(/ /, $list);

For example:

my $list = "fred joe brown sam";
my %HoA = ();
my $key = "jacob";
@{$HoA{$key} = split(/ /, $list);
foreach my $item (@{$HoA{$key}})
{
    print "Test item: $nextItem\n";
}

You will get:
Test item: fred
Test item: joe
Test item: brown
Test item: sam

Edit: Add use strict; to the top of your program. Basically you are attempting to use HoA as an array when you have a hash defined. You are referencing the contents of your hash improperly. To do it properly you really really need to have a $ between the @ and HoA. Perl is typeless and will let you get away with murder if you don't use strict;. A reference excerpt from oreilly might clear a few things up.

my @testarray is an array
my %hash is a hash
$hash{$el1} = \@array is a hash element that has the value of a ref to an array
@{$hash{$el1}} = @array is a hash element that contains an array

like image 176
scrappedcola Avatar answered Sep 24 '22 13:09

scrappedcola


Each entry in your hash is a reference to an array. For example:

$my_hash{$key}

is a reference to an array and not an array. $my_hash{$key} is merely pointing to an area in memory where that array lives. To dereference it, you put the array symbol in front:

@{ my_hash{$key} }

Things get a bit hairier when we start talking about the elements:

${ my_hash{$key} }[0]

is the first element of that array. You can imagine if that array consisted of hashes to other arrays, the syntax can get quite obtrude. Fortunately, Perl has a clean way of handling it:

$my_hash{$key}->[0];

That's exactly the same as above, but easier to understand syntax. Sometimes, it's easier to use intermediate variables just so you can refer to things without all the dereferencing:

my %hash_of_array_refs;

foreach my $key (sort keys %hash_of_array_refs) {
    my @array = @{ $hash_of_array_refs{$key} };    #Dereference
    foreach my $element (@array) {                 #Much easier to read and understand
        say "First element is $array[0]";
        say "last element is $array[$#array]";
        say "This element: $element";
    }
}

Without dereferencing you get this:

my %hash_of_array_refs;

foreach my $key (sort keys %hash_of_array_refs) {
    foreach my $element (@{ $hash_of_array_refs{$key} } ) {                 #Much easier to read and understand
        say "First element is " . $hash_of_array_refs->[0];
        say "last element is " . $hash_of_array_refs->[$#{ $hash_of_array_refs{key} } ]";
        say "This element: $element";
    }
}
like image 35
David W. Avatar answered Sep 23 '22 13:09

David W.