Perl: Hash ref accessing array of keys

hashperl

I have a question that seems basic, but I can't figure out. Say that I have a hash reference in Perl. I want to get an array of values through an array of keys.

Here's how it'd work with a hash, not a hash reference:

my %testHash = ( "a" => 1, "b" => 2, "c" => 3 );
my @testKeys = ("a", "b", "c");

my @testValues = @testHash{@testKeys};

Now suppose I have a hash reference,

my $hashRef = {"a" => 1, "b" => 2, "c" => 3};

I've tried the following two ways:

my @values = @{$hashRef->{@testKeys}};
my @values = $hashRef->{@testKeys};

But neither is correct. Is there a correct way, or do I just have to dereference the hash ref every time I want to do this?

Best Answer

You're close:

my @values = @$hashref{@testKeys};     ## (1)

or

my @values = @{$hashref}{@testKeys};   ## (2)

For more examples, see "Slices" in the perllol documentation.

"Using References" in the perlref documentation gives the general rules.

1. Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a simple scalar variable containing a reference of the correct type.

This explains why (1) works: you replaced the identifier testHash with the simple scalar $hashRef.

2. Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a BLOCK returning a reference of the correct type.

Snippet (2) above is nearly the same but has a little bulkier syntax. In place of the identifier testHash, you write a block returning a reference to a hash, i.e., {$hashRef}.

The braces here enclose a bona fide block, so you can compute and return a reference, as in

push @{ $cond ? \@a1 : \@a2 }, "some value";
Related Topic