2

我需要创建多维哈希。

例如我做了:

$hash{gene} = $mrna;
if (exists ($exon)){
  $hash{gene}{$mrna} = $exon;
}
if (exists ($cds)){
  $hash{gene}{$mrna} = $cds;
}

其中$gene, $mrna, $exon,$cds是唯一 ID。

但是,我的问题是我希望将 $gene 和 $mrna 的一些属性包含在哈希中。例如:

$hash{$gene}{'start_loc'} = $start;
$hash{gene}{mrna}{'start_loc'} = $start;

等等但是,这是声明哈希的可行方式吗?如果我同时调用$hash{$gene}两者$mrna并将start_loc被打印。有什么解决办法?

在这种情况下,我将如何为同一个键 $gene 和 $mrna 添加多个值作为键。

任何建议将不胜感激。

4

2 回答 2

6

您需要做的是阅读Perl 参考教程

简单回答你的问题:

Perl 哈希只能将单个值作为键。但是,该单个值可以是对另一个哈希的内存位置的引用。

my %hash1 = ( foo => "bar", fu => "bur" };  #First hash
my %hash2;
my $hash{some_key} = \%hash1;   #Reference to %hash1

而且,没有什么可以阻止第一个哈希包含对另一个哈希的引用。一路下来都是乌龟!.

所以是的,您可以根据需要拥有一个复杂而令人费解的结构,并且可以使用任意数量的子哈希。或者也混合一些数组。

由于各种原因,我更喜欢->使用这些复杂结构时的语法。我发现对于更复杂的结构,它更容易阅读。但是,主要是它让您记住这些是参考而不是实际的多维结构。

例如:

$hash{gene}->{mrna}->{start_loc} = $start;  #Quote not needed in string if key name qualifies as a valid variable name.

最好的办法是将散列视为一种结构。例如:

my $person_ref = {};   #Person is a hash reference.
my $person->{NAME}->{FIRST} = "Bob";
my $person->{NAME}->{LAST} = "Rogers";
my $person->{PHONE}->{WORK}->[0] = "555-1234"; An Array Ref. Might have > 1
my $person->{PHONE}->{WORK}->[1] = "555-4444";
my $person->{PHONE}->{CELL}->[0] = "555-4321";
...

my @people;
push @people, $person_ref;

现在,我可以用我所有的人加载我的@people 数组,或者使用哈希:

my %person;
$person{$bobs_ssn} = $person;   #Now, all of Bob's info is index by his SSN.

因此,您需要做的第一件事就是考虑您的结构应该是什么样子。您的结构中有哪些字段?有哪些子领域?弄清楚你的结构应该是什么样子,然后将你的哈希设置成这样。弄清楚它将如何存储和键入。

请记住,此哈希包含对您的基因(或其他)的引用,因此您要明智地选择密钥。

阅读教程。然后,尝试一下。理解起来并不那么复杂。但是,维持它可能是一种负担。

当你说 时use strict;,你给自己一些保护:

my $foo = "bar";
say $Foo;    #This won't work!

这是行不通的,因为你没有声明$Foo,你声明了$foo。可以捕获输入错误的use stict;变量名,但是:

my %var;
$var{foo} = "bar";
say $var{Foo};    #Whoops!

这不会被捕获(除非可能$var{Foo}尚未初始化。use strict;编译指示无法检测到键入键的错误。

在您熟悉引用之后,下一步是转向面向对象的 Perl。也有一个教程

所有面向对象的 Perl 所做的就是获取您的哈希引用,并将它们转换为objects。然后,它会创建子程序来帮助您跟踪操作对象。例如:

 sub last_name {
    my $person = shift;   #Don't worry about this for now..
    my $last_name = shift;

    if ( exists $last_name ) {
      my $person->{NAME}->{LAST} = $last_name;
    }
    return $person->{NAME}->{LAST};
}

当我使用这个子程序设置我的姓氏时......我的意思是方法,我保证键是$person->{NAME}->{LAST}而不是$person->{LAST}->{NAME}$person->{LAST}->{NMAE}。或$person->{last}->{name}

主要问题不是学习机制,而是学习应用它们。因此,请仔细考虑您希望如何表示您的项目。这是关于你想要什么字段,以及你将如何提取这些信息。

于 2013-09-02T23:16:27.783 回答
-1

您可以尝试将每个值推送到数组哈希中:

my (@gene, @mrna, @exon, @cds);

my %hash;
push  @{ $hash{$gene[$_]} }, [$mrna[$_], $exon[$_], $cds[$_] ] for 0 .. $#gene;

这种方式gene是关键,有多个值($mrna, $exon, $cds)与之关联。

迭代键/值如下:

for my $key (sort keys %hash) {
    print "Gene: $key\t";
        for my $value (@{ $hash{$key} } ) {
            my ($mrna, $exon, $cds) = @$value; # De-references the array
            print "Values: [$mrna], [$exon], [$cds]\n";
        }
}

我之前问过的一个问题的答案可能会有所帮助(哈希键在 perl 中有多个“子值”吗?)。

于 2013-09-02T16:54:07.420 回答