向perl哈希中的键添加多个值

向perl哈希中的键添加多个值,perl,perl-hash,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;
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} = $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;
 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};
}
但是,这是声明散列的可行方法吗?如果我调用
$hash{$gene}
将同时打印
$mrna
start\u loc
。解决办法是什么

在本例中,如何为同一个键$gene和$mrna添加多个值作为键


如果您有任何建议,我们将不胜感激。

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

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

my %hash;
push  @{ $hash{$gene[$_]} }, [$mrna[$_], $exon[$_], $cds[$_] ] for 0 .. $#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哈希只能对一个键取一个值。但是,该单个值可以是对另一个哈希的内存位置的引用

my %hash1 = ( foo => "bar", fu => "bur" };  #First hash
my %hash2;
my $hash{some_key} = \%hash1;   #Reference to %hash1
而且,没有任何东西可以阻止第一个散列包含对另一个散列的引用

所以,是的,你可以有一个复杂的,复杂的结构,你想用多少子散列就用多少子散列。或者混合在一些数组中

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

例如:

$hash{$gene}{'start_loc'} = $start;
$hash{gene}{mrna}{'start_loc'} = $start;
$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;
 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};
}
最好的办法是将哈希看作一个结构。例如:

$hash{$gene}{'start_loc'} = $start;
$hash{gene}{mrna}{'start_loc'} = $start;
$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;
 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};
}
现在,我可以用我所有的人加载@people数组,或者使用散列:

my %person;
$person{$bobs_ssn} = $person;   #Now, all of Bob's info is index by his SSN.
因此,您需要做的第一件事是思考您的结构应该是什么样子。您的结构中有哪些字段?子字段是什么?弄清楚你的结构应该是什么样的,然后把你的散列设置成那样。弄清楚它将如何存储和键入

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

阅读教程。那么,试试你的手。理解起来并不那么复杂。然而,它可以是一只熊来维持

当你说
时,使用strict,您可以为自己提供一些保护:

my $foo = "bar";
say $Foo;    #This won't work!
这不起作用,因为您没有声明
$Foo
,而是声明了
$Foo
使用stict可以捕获键入错误的变量名,但是:

my %var;
$var{foo} = "bar";
say $var{Foo};    #Whoops!
这将不会被捕获(可能除了
$var{Foo}
尚未初始化。
使用strict;
pragma无法检测键入密钥时的错误

在熟悉了引用之后,下一步是转向面向对象的Perl

面向对象的Perl所做的一切就是获取散列引用,并将它们转换为对象。然后,它创建子例程,帮助您跟踪操作对象。例如:

$hash{$gene}{'start_loc'} = $start;
$hash{gene}{mrna}{'start_loc'} = $start;
$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;
 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}


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

exists
是一个只对哈希元素查找有效的特殊运算符。您不能在简单的标量变量上使用它变量是这样的。
$gene
这里是一个字符串,而不是整数。那么我该如何迭代呢?但是,我的问题是
$mrna
也是
$exon
$cds
的一个键。我该如何实现它?换句话说,我的多个值也是键。有解决方案吗?你需要它的特殊原因吗结构?