Ваш код, но с правильными отступами, чтобы его можно было прочитать.
$Interaction{$TrGene} = {
CisGene => $CisGene,
E => $e,
Q => $q,
};
push @{$Interaction{$TrGene}}, $CisGene;
Код объяснил:
Вы присваиваете список пар ключ-значение анонимному хешу, используя фигурные скобки {}
, и назначаете эту ссылку хеша на ключ $TrGene
в хеше %Interaction
. Затем вы пытаетесь использовать это значение в качестве ссылки на массив, окружая его @{ ... }
, что не работает.
Если вы введете хеш-ключ с другими значениями, вы перезапишите его. Давайте возьмем несколько практических примеров, это действительно довольно легко.
$Interaction{'foobar'} = {
CisGene => 'Secret code',
E => 'xxx',
Q => 'yyy',
};
Теперь вы сохранили ссылку на хеш под ключом 'foobar'
. Этот хэш на самом деле является независимой ссылкой на структуру данных. Я думаю, что легче отслеживать структуры, если вы думаете о них как о скалярах: хеш (или массив) может содержать только скаляры.
Хеш %Interaction
может содержать несколько ключей, и если вы ввели данные, как указано выше, все значения будут ссылками на хеш. E.g.:
$hash1 = { # note: curly brackets denote an anonymous hash
CisGene => 'Secret code',
E => 'xxx',
Q => 'yyy',
};
$hash2 = {
CisGene => 'some other value',
E => 'foo',
Q => 'bar',
};
%Interaction = ( # note: regular parenthesis denote a list
'foobar' => $hash1, # e.g. CisGene => 'Secret code', ... etc. from above
'barbar' => $hash2 # e.g. other key value pairs surrounded by {}
...
);
Тип значения, содержащийся в $hash1
и $hash2
, теперь является ссылкой, адресом данных в памяти. Если вы напечатаете его print $hash1
, вы увидите что-то вроде HASH(0x398a64)
.
Теперь, если вы введете новое значение в %Interaction
, используя существующий ключ, этот ключ будет перезаписан. Потому что ключ хеша может содержать только одно значение: скаляр. В нашем случае ссылка на хеш.
В вашем примере вы пытаетесь использовать значение ключа 'foobar'
в качестве ссылки на массив (что глупо, потому что, как вы можете видеть выше, это ссылка на хеш):
push @{$Interaction{$TrGene}}, $CisGene;
Переписано:
push @{ $hash1 }, 'Secret code'; # using the sample values from above
Нет ... это не работает.
Вам нужен новый контейнер. Вместо этого мы сделаем значение ключа 'foobar'
ссылкой на массив:
%Interaction = (
'foobar' => $array1,
...
);
Где:
$array1 = [ $hash1, $hash2 ];
или
$array1 = [ # note the square brackets to create anonymous array
{ # curly brackets for anonymous hash
CisGene => 'Secret code',
E => 'xxx',
Q => 'yyy',
}, # comma sign to separate array elements
{ # start a new hash
CisGene => 'Some other value',
E => 'foo',
Q => 'bar',
} # end
]; # end of $array1
Теперь это довольно громоздкий способ обозначения вещей, поэтому давайте упростим его:
$CisGene = 'foobar';
$e = 'xxx';
$q = 'yyy';
my $hash1 = {
CisGene => $CisGene,
E => $e,
Q => $q,
};
push @{$Interaction{$TrGene}}, $hash1;
Или вы можете покончить с временной переменной $hash1
и назначить ее напрямую:
push @{$Interaction{$TrGene}}, {
CisGene => $CisGene,
E => $e,
Q => $q,
};
А при доступе к элементам:
for my $key (keys %Interaction) { # lists the $TrGene keys
my $aref = $Interaction{$key}; # the array reference
for my $hashref (@$aref) { # extract hash references, e.g. $hash1
my $CisGene = $hashref->{'CisGene'};
my $e = $hashref->{'E'};
my $q = $hashref->{'Q'};
}
}
Обратите внимание на использование оператора стрелки при работе непосредственно со ссылками. Вы также можете сказать $$hashref{'CisGene'}
.
Или напрямую:
my $CisGene = $Interaction{'foobar'}[0]{'CisGene'};
Я рекомендую прочитать perldata . Очень удобный модуль - Data :: Dumper . Если вы делаете:
use Data::Dumper;
print Dumper \%Interaction; # note the backslash, Dumper wants references
Он распечатает вашу структуру данных для вас, что позволяет очень легко увидеть, что вы делаете. Обратите внимание на использование скобок и фигурных скобок для обозначения массивов и хэшей.