在perl哈希中为key添加多个值

时间:2013-09-02 16:43:57

标签: perl perl-hash

我需要创建多维哈希。

例如我已经完成了:

$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},则会打印$mrnastart_loc。可能是什么解决方案?

如何为同一个键$ gene添加多个值,并且在这种情况下$ mrna是键。

任何建议都将受到赞赏。

2 个答案:

答案 0 :(得分:5)

您需要做的是阅读Perl Reference Tutorial

简单回答你的问题:

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

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

并且,没有什么能阻止第一个哈希包含对另一个哈希的引用。 It's turtles all the way down!

所以,是的,您可以根据需要使用任意数量的子哈希来构建复杂且复杂的结构。或者混合一些数组。

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

例如:

$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,你声明了$foouse stict;可以捕获错误输入的变量名称,但是:

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

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

下一步,在您对引用感到满意之后,转向面向对象的Perl。有Tutorial for that too

所有面向对象的Perl都是采用哈希引用,并将它们转换为对象。然后,它创建子程序,帮助您跟踪操纵对象。例如:

 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}或{{1} }。或$person->{LAST}->{NMAE}

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

答案 1 :(得分:-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";
        }
}

我之前问过的问题的答案可能有所帮助(Can a hash key have multiple 'subvalues' in perl?)。