我需要创建多维哈希。
例如我已经完成了:
$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是键。
任何建议都将受到赞赏。
答案 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
,你声明了$foo
。 use 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?)。