您的代码,但是正确缩进以便更易读。
$Interaction{$TrGene} = {
CisGene => $CisGene,
E => $e,
Q => $q,
};
push @{$Interaction{$TrGene}}, $CisGene;
代码解释:
你使用花括号{}
为匿名哈希分配一个键值对列表,并将该哈希引用分配给%Interaction
哈希中的$TrGene
键。然后你尝试使用@{ ... }
将该值作为数组引用,但这是不起作用的。
如果你使用不同的值输入哈希键,则会覆盖它们。让我们看一些实际的例子,这真的很容易。
$Interaction{'foobar'} = {
CisGene => 'Secret code',
E => 'xxx',
Q => 'yyy',
};
现在你已经将一个哈希引用存储在键
'foobar'
下。该哈希实际上是指向数据结构的独立引用。如果你将它们视为标量,那么跟踪结构会更容易:哈希(或数组)只能包含标量。
哈希
%Interaction
可能包含许多键,如果你像上面那样输入数据,则所有值都将是哈希引用。例如:
$hash1 = {
CisGene => 'Secret code',
E => 'xxx',
Q => 'yyy',
};
$hash2 = {
CisGene => 'some other value',
E => 'foo',
Q => 'bar',
};
%Interaction = (
'foobar' => $hash1,
'barbar' => $hash2
...
);
$hash1
和
$hash2
所包含的值类型现在是引用,即指向内存中数据的地址。如果你输出
print $hash1
,你将看到像
HASH(0x398a64)
这样的内容。
现在,如果你使用现有的键向
%Interaction
输入一个新值,那么该键将被覆盖。因为哈希键只能包含一个值:一个标量。在我们的例子中,它是一个哈希的引用。
在你的示例中,你试图使用
'foobar'
键的值作为数组引用(这很荒谬,因为正如你现在可以看到的,它是一个哈希引用):
push @{$Interaction{$TrGene}}, $CisGene;
Rewritten:
push @{ $hash1 }, 'Secret code'; # using the sample values from above
不行...这样不起作用。
你需要一个新的容器。我们将把键'foobar'
的值改为数组引用:
%Interaction = (
'foobar' => $array1,
...
);
地点:
$array1 = [ $hash1, $hash2 ];
或者
$array1 = [
{
CisGene => 'Secret code',
E => 'xxx',
Q => 'yyy',
},
{
CisGene => 'Some other value',
E => 'foo',
Q => 'bar',
}
];
现在,这么描述有些繁琐,让我们简单点说:
$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) {
my $aref = $Interaction{$key};
for my $hashref (@$aref) {
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
它会为您打印出数据结构,这使得很容易看到您在做什么。请注意它使用方括号和花括号来表示数组和哈希表。