2016-07-07 3 views
0

У меня есть многомерный хэш, который выглядит следующим образом:Pass вложенной хэш подпрограмма

my %hashTable; 
$hashTable{'1'}{'A'} = "red"; 
$hashTable{'1'}{'B'} = "blue"; 
$hashTable{'2'}{'A'} = "orange"; 
$hashTable{'2'}{'B'} = "purple"; 

Я хочу, чтобы передать внутренний хэш в качестве аргумента в подпрограмму. Например,

hashFunc($hashTable{'2'}); 

sub hashFunc{ 
    my %innerHash = $_[0]; 
} 

Однако, когда я вызываю функцию как hashFunc($hashTable{'2'}), я получаю ошибку

Reference found where even-sized list expected 

Как правильно обеспечить внутренний хэш в качестве аргумента в подпрограмму?

+0

какую версию Perl вы используете. У меня не было ошибок с этим кодом. – Arseniy

+0

Я также не получаю эту ошибку. Пожалуйста, уточните вашу среду. –

+3

Это абсолютно ошибка в каждой версии perl. Включите предупреждения, если вы их не увидите. – mob

ответ

3

Многомерные структуры данных собираются посредством ссылки.

$hashtable{'2'} - скалярное значение, это ссылка на хэш.

Чтобы использовать его в подпрограмме, вам необходимо разыменованием его - либо перед тем отправка:

hashFunc(%{$hashtable{'2'}}); 

Который посылает список значений (которые затем можно назначить в хэш, как вы делаете).

Или в хэш:

my %innerHash = %{$_[0]}; 

Однако, как Бородин отмечает, - это приведет к тому, структура данных, подлежащих копированию, и это неэффективно и редко.

Таким образом, вы могли бы вместо этого:

my ($innerHash) = @_; 

И тогда вы можете получить доступ к $innerHash через операторов разыменования, как:

print $innerHash -> {'A'}; 
foreach my $key (keys %$innerHash) { 
    print $key,"\n"; 
} 

и т.д.

+3

*** Абсолютно нет! *** Обманчиво предлагать любое из этих решений. Выделение хэша крайне редко необходимо, и далеко не очевидно, что результатом является одноуровневая копия оригинала, которая будет дублировать данные без необходимости. Ссылка должна быть передана непосредственно подпрограмме – Borodin

2

Вам нужно разыменовать внутренний хеш, если вам нужно использовать его как хэш.

Вы можете сделать это в подпрограмме

hashFunc($hashTable{2}); 
sub hashFunc { 
    my %innerHash = %{ $_[0] }; 

или в коде вызова

hashFunc(%{ $hashTable{2} }); 
sub hashFunc { 
    my %innerHash = @_; 

Но, как правило, не нужно использовать хэш, вы можете просто использовать ссылку на хеш непосредственно.

hashFunc($hashTable{2}); 
sub hashFunc { 
    my $innerHashRef = shift; 
    # Whatever you need to do with the hash: 
    $innerHashRef->{key}{A} = ... 
    for my $key (keys %$innerHashRef) { 
    ... 
+0

Вы уверены, что во втором случае вам не нужно делать 'my% innerHash = @_;'? – Dada

+0

@ Дада: Верно, спасибо. – choroba

+0

У этой проблемы есть проблема с решением [Sobrique] (http://stackoverflow.com/a/38247206/622310). Разбор разворота всего хэша является расточительным и почти бесполезным – Borodin

4

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

Вам необходимо назначить скалярное значение в пределах вашей подпрограммы, как этот

hashFunc($hashTable{'2'}); 

sub hashFunc{ 
    my ($innerHash) = @_; 
    # same as my $innerHash = $_[0] 
    ... 
} 

ты ничего о том, что вы хотите сделать с вторичной хэш не говорят, но в целом вы можете получить доступ к элементу внутренней хэш с помощью $innerHash->{key}, или вы можете использовать keys, values или each операторы путем разыменования значения; например for my $k (keys %$innerHash) { ... }

Вы должны взглянуть на Perl references short introduction и Perl data structures intro для получения дополнительной информации