Perl: хэш-обратный доступ к массиву ключей

У меня есть вопрос, который кажется основным, но я не могу понять. Скажем, что у меня есть хеш-ссылка в Perl. Я хочу получить массив значений через массив ключей.

Вот как это работает с хэшем, а не с хеш-ссылкой:

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

my @testValues = @testHash{@testKeys};

Теперь предположим, что у меня есть хеш-ссылка,

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

Я пробовал следующие два способа:

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

Но ни то, ни другое неверно. Правильно ли это, или мне просто нужно разыгрывать хэш-ref каждый раз, когда я хочу это сделать?

Ответы

Ответ 1

Вы близко:

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

или

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

Дополнительные примеры см. в "Slices" в документации по perllol.

"Использование ссылок" в документации perlref содержит общие правила.

1. В любом месте, где вы поместите идентификатор (или цепочку идентификаторов) как часть имени переменной или подпрограммы, вы можете заменить идентификатор простой скалярной переменной, содержащей ссылку правильного типа.

Это объясняет, почему (1) работает: вы заменили идентификатор testHash на простой скаляр $hashRef.

2. В любом месте, где вы поместите идентификатор (или цепочку идентификаторов) как часть имени переменной или подпрограммы, вы можете заменить идентификатор BLOCK, возвращающим ссылку правильного типа.

Фрагмент (2) выше почти такой же, но имеет немного более громоздкий синтаксис. Вместо идентификатора testHash вы пишете блок, возвращающий ссылку на хеш, т.е. {$hashRef}.

Здесь фигурные скобки заключают в себе добросовестный блок, поэтому вы можете вычислять и возвращать ссылку, как в

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