我正在尝试创建一个数据结构来存储我从数据库中删除的数据:
$Interaction{$TrGene}={
CisGene => $CisGene,
E => $e,
Q => $q,};
单个$ TrGene与许多CisGenes(具有唯一的E& Q)相关联。 e.g:
TrGene1 CisGene1 Q1 E2
TrGene1 CisGene2 Q2 E3
最后一个TrGene1会覆盖它之前的那些。我认为我需要创建对数组的引用,但在阅读此网页后,请不要完全理解如何执行此操作:http://perldoc.perl.org/perlreftut.html
我试图在该网页上使用国家/城市示例,但效果不是很好:
$Interaction{$TrGene}={
CisGene => $CisGene,
E => $e,
Q => $q,};
push @{$Interaction{$TrGene}}, $CisGene;
我收到错误'不是ARRAY ref'。我也只在那里使用了$ CisGene,但它不需要覆盖E&该CisGene的Q值。 (这个哈希知道CisGene是否与特定的E和Q相关联,或者我是否需要为此创建另一层哈希?)
由于
答案 0 :(得分:3)
您的代码,但正确缩进以便可读。
$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
它将为您打印出您的数据结构,这使您可以很容易地看到自己在做什么。请注意使用括号和大括号来表示数组和散列。
答案 1 :(得分:2)
像
这样的东西push @{ $Interaction{ $TrGene }{members} }, $CisGene;
应该有用。
$Interaction{$TrGene}
不能是数组引用,因为您只是为它分配了一个哈希引用。
当然,如果您想要E
和Q
的组合(我会假设它在$TrGene
键中指示,或者您是可能会造成更多混乱。)你会想要更像这样的东西:
$Interaction{ $TrGene } //= { E => $e, Q => $q };
push @{ $Interaction{ $TrGene }{CisGenes} }, $CisGene;
如果E
和Q
取决于$TrGene
的值,那么您将获得所需的分组。否则,您可以按如下方式考虑它们的下标:
push @{ $Interaction{ $e }{ $q } }, $CisGene;
并获得E
,Q
和$CisGene
之间更大关联的映射。
答案 2 :(得分:2)
你差点把它放在你试图推入arrayref的地方。问题是您已经为$Interaction[$TrGene}
分配了一个hashref,然后尝试将其用作@{ $Interaction{$TrGene} }
的arrayref。
@{ $Interaction{$TrGene} }
表示:
$Interaction{$TrGene}
@{ ... }
。例如。你可以这样做:@array = @{$Interaction{$TrGene}}
。$Interaction{$TrGene}
中没有值,则会在该点自动创建arrayref(称为自动生存)。因此,假设您已经创建了这些hashref:
my $CisGene1 = {
CisGene => 'CisGene1',
E => 'E1',
Q => 'Q1',
};
my $CisGene2 = {
CisGene => 'CisGene2',
E => 'E3',
Q => 'Q2',
};
您可以将每个推送到您的arrayref:
push @{ $Interaction{$TrGene} }, $CisGene1, $CisGene2;