Разыменование ключа массива в Perl - PullRequest
2 голосов
/ 27 августа 2010

Рассмотрим скрипт Perl:

use strict;

my %new;
my $test_ref = [24, 26, 55];
$new{$test_ref} = 10;

foreach my $key (keys %new){
    print $key->[0];
}

Когда я пытаюсь получить доступ к этому элементу, он выдает ошибку вроде:

Невозможно использовать строку ("ARRAY (0x...) ") в качестве массива ref

Почему?

Ответы [ 4 ]

3 голосов
/ 27 августа 2010

Поскольку хеш-ключ всегда является строковым, а строковое значение массива REFERENCE (которым является $test_ref) является именно таким: "ARRAY(0x...)".Это отличается от Java-карт, которые могут хранить произвольный объект в качестве ключа.

Поэтому ваш хэш будет иметь 1 пару значений кет-значений, причем ключом является строка ""ARRAY(0x...)""

Итак, когда у вас есть цикл for, он перебирает все ключи (все 1 из них), а затем присваивает значение ключа (строка "ARRAY(0x...)") переменной $key.

Youзатем попытайтесь разыменовать массив этой строки - что, конечно, невозможно сделать, поскольку это не ссылка на массив - это просто строка, содержащая строковое представление того, что раньше было ссылкой на массив.

Если вы хотите, чтобы «24, 26, 55» были 3 хеш-ключами, вы можете сделать это:

my %new = map { $_ => 10 } @$test_ref;

Если вы действительно хотите сохранить список в хеш-ключе, это выполнимоно не всегда (в вашем случае список целых чисел вы можете, но он медленный, неуклюжий, и я не могу представить, когда вы когда-нибудь захотите.

# Trivial example:
my $test_ref = [24, 26, 55];
$new{ join(",",@$test_ref) } = 10;
foreach my $key (keys %new){
    my @list = split(/,/,$key);
    print $list[0];
}

Этот подход имеет некоторые потери производительностии может быть немного оптимизирован (например, путем запоминания результатов разделения). Но опять же, fили в значительной степени по ЛЮБОЙ причине, по которой вы, возможно, захотите это сделать, возможно, есть лучшие решения.

2 голосов
/ 27 августа 2010

Хэш-ключи обычно имеют строковое форматирование, поэтому они теряют способность работать в качестве эталона.

Основной модуль Tie :: RefHash предоставляет эту возможность:

use strict;
use warnings;
use Tie::RefHash;

tie my %new, 'Tie::RefHash';
my $test_ref = [24, 26, 55];
$new{$test_ref} = 10;

foreach my $key (keys %new){
    print $key->[0];
}

Хорошая работа, используя строгий.Но предупреждения еще важнее.

0 голосов
/ 27 августа 2010

Если вы хотите получить доступ к ссылке на массив $test_ref, то вы хотите использовать синтаксис массива (квадратные скобки)

$test_ref->[0];

Если вы хотите получить доступ к хешу %new, используйтесинтаксис хеша (фигурные скобки)

$new{$key}

То, что вы делаете, использует ссылку на массив $test_ref в качестве ключа в хеш %new - что делает perl, это преобразовывает ссылку на массив в строку для использованияключ.Это строка, а не ссылка, возвращаемая keys.

Вы не можете использовать ссылки в качестве ключей, а затем вернуть ссылку обратно (тривиально).

0 голосов
/ 27 августа 2010

Я предполагаю (и могу ошибаться), что вы хотите назначить 24, 26 и 55 в качестве ключей %new.

Если вы хотите сделать это, вам нужно следующее:

use strict;

my %new;
my $test_ref = [24, 26, 55];

@new{@$test_ref} = (10) x @$test_ref;

print "$new{$_}\n" foreach keys %new;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...