Вашият код, но с правилен отстъп, така че да е четим.
$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
може да съдържа няколко ключове и ако сте въвели данни като по-горе, всички стойности ще бъдат препратки към хеш. напр.:
$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 ];
or
$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
Той ще отпечата структурата на вашите данни вместо вас, което прави много лесно да видите какво правите. Обърнете внимание на използването на скоби и къдрави скоби за обозначаване на масиви и хешове.
person
TLP
schedule
03.01.2012