perl - 使用 Perl 将多个值存储在散列的散列中的一个键中

标签 perl hash reference perl-data-structures

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

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

单个 $TrGene 与多个 CisGene(具有独特的 E &Q)相关联。 例如:

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 引用”。我也只在那里使用了 $CisGene,但是它不需要覆盖该 CisGene 的 E & Q 值。 (那么这个哈希会知道 CisGene 与特定的 E 和 Q 相关联,还是我需要为此创建另一层哈希?)

谢谢

最佳答案

您的代码,但适当缩进以使其可读。

$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 ];

$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

它会为你打印出你的数据结构,这让你很容易看到你在做什么。请注意它使用方括号和大括号来表示数组和散列。

关于perl - 使用 Perl 将多个值存储在散列的散列中的一个键中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8711632/

相关文章:

ruby - 在 Ruby 中更新哈希值

c++ - 类定义中的引用变量

reference - 在 Rust 中,为什么 std::iter::Iterator 的 min 函数返回一个引用?

c# - 如何在vs2012中添加对程序集的引用

c++ - 比较 AES 与 MD4 或其他

perl - 在 shell/Perl 脚本中保存密码的最佳实践?

perl - 使用 perl 模块 "vCard::AddressBook"将节点类别添加到 vcard

perl - 为什么要使用这个奇怪的包名变体?

python - 如何从 Perl 哈希在 Python 中创建等效的字典?

perl - 如何使用 block 作为 'or' 子句而不是简单的骰子?