使用 Perl 在一个哈希哈希中的一个键中存储多个值



我正在尝试创建一个数据结构来存储我正在从数据库中提取的数据:

$Interaction{$TrGene}={
CisGene => $CisGene,
E => $e,
Q => $q,};

单个$TrGene与许多顺式基因(具有独特的E&Q(相关联。例如:

TrGene1 顺基因1 Q1 E2

TrGene1 顺基因2 Q2 E3

最后一个 TrGene1 覆盖了之前的那些。我认为我需要创建对数组的引用,但在阅读此网页后不完全理解应该如何做到这一点:http://perldoc.perl.org/perlreftut.html

我尝试在该网页上使用国家/城市示例,但不是很成功:

$Interaction{$TrGene}={
CisGene => $CisGene,
E => $e,
Q => $q,};
push @{$Interaction{$TrGene}}, $CisGene;

我收到错误"不是数组参考"。我也只在那里使用了$CisGene,但是它不需要覆盖该 CisGene 的 E 和 Q 值。(那么这个哈希值会知道 CisGene 与特定的 E 和 Q 相关联,还是我需要为此创建另一层哈希值?

谢谢

您的代码,但正确缩进,以便可读。

$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 = {  # 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::D umper。如果您这样做:

use Data::Dumper;
print Dumper %Interaction; # note the backslash, Dumper wants references

它将为您打印出您的数据结构,这使得您很容易看到您在做什么。记下它使用括号和大括号来表示数组和哈希。

类似的东西

push @{ $Interaction{ $TrGene }{members} }, $CisGene;

应该工作。

$Interaction{$TrGene}不能是数组引用,因为您刚刚为其分配了一个哈希引用。

当然,你应该在分配之前先检查一下,如果你想要EQ的组合(我会假设它在$TrGene键中指示,否则,你可能会制造更多的混乱。

 $Interaction{ $TrGene } //= { E => $e, Q => $q };
 push @{ $Interaction{ $TrGene }{CisGenes} }, $CisGene;

这样,如果EQ依赖于 $TrGene 的值,您将获得所需的分组。否则,您可以将它们视为下标,如下所示:

push @{ $Interaction{ $e }{ $q } }, $CisGene;

并获得EQ$CisGene之间具有更大关联的映射。

你几乎在试图推入数组引用的地方拥有它。问题是你已经为$Interaction[$TrGene}分配了一个哈希引用,然后尝试将其用作带有@{ $Interaction{$TrGene} }的数组引用。

@{ $Interaction{$TrGene} }意味着:

  • 您正在获取哈希值$Interaction{$TrGene}
  • 然后取消引用数组@{ ... } . 例如,您可以这样做:@array = @{$Interaction{$TrGene}} .
  • 如果 $Interaction{$TrGene} 中没有值,则此时将自动创建 arrayref(称为自动激活(。

因此,假设您已经创建了这些哈希引用:

my $CisGene1 = {
    CisGene => 'CisGene1',
    E => 'E1',
    Q => 'Q1',
};
my $CisGene2 = {
    CisGene => 'CisGene2',
    E => 'E3',
    Q => 'Q2',
};

您可以将它们中的每一个推送到您的 arrayref 中:

push @{ $Interaction{$TrGene} }, $CisGene1, $CisGene2;

最新更新