3

我有一个散列,它应该包含某些链接到它们自己的数组的键。更具体地说,哈希键是质量值,数组是序列名称。如果已经有该质量的数组,我想将序列名称添加到与相关质量相关联的数组中。如果没有,我想创建一个并将序列名称添加到其中。所有这些都是在一个while循环中完成的,一个一个地遍历所有序列。

我试图在Perl 中做类似的事情如何从数组哈希中检索数组?但我似乎无法做到这一点。

我刚刚收到这些错误消息:标量值@{hash{$q} 最好在 asdasd.pl 第 69 行写成 ${hash{$q}。全局符号“@q”需要显式包名称 asdasd.pl 第 58 行。其他一些人也是。

这是我尝试过的示例:

my %hash;
while (reading the sequences) {
    my $q = "the value the sequence has";
    my $seq = "the name of the sequence";

    if (exists $hash{$q}) {
        push (@{$hash{$q}}, $seq);
    } else {
        $hash{$q} = \@q;
        $hash{$q} = [$seq];
        next;
    }
}

这显然不应该是一个非常复杂的问题,但我是 perl 的新手,这种问题感觉很困难。我已经从不同的地方搜索了这个,但似乎有些东西我没有意识到,而且它可能也很明显。

4

2 回答 2

4

您可以使用 perl 所称的 autovivification来简化此操作。您的代码不需要那个中央 if 语句。您可以将其归结为:

    push @{ $hash{$q} }, $seq;

如果散列中不存在特定的键,perl 会自动激活它,因为它可以推断出你想要一个数组引用。

你可以通过谷歌搜索找到更多关于自动复活的资源。这是一个足够独特的词,绝大多数热门歌曲似乎都是相关的。:-)

于 2013-07-10T13:30:19.667 回答
2

您实际上非常接近,但有一些注意事项:

  1. 在您的else块中,您将引用分配给@q您的哈希,然后立即用 覆盖它[$seq],只有哈希上的最后一个操作将保持

  2. 您不需要next在循环结束时,如果循环体中没有更多要执行的语句,它将自动进入下一次迭代。

其他一切似乎都很好,这是我的修改和我使用的测试数据(因为我对 DNA 序列一无所知,我只使用了我记得的高中生物学字母)

输入文件:

A 1
T 2
G 3 
A 3
A 2
G 5
C 1
C 1
C 2
T 4

代码:

use strict;
use warnings FATAL => 'all';

# open file for reading
open(my $fh, '<', 'test.txt');

my %hash;
while ( my $line = <$fh> ) { # read a line

    # split the line read from a file into a sequence name and value
    my ($q, $seq) = split(/\s+/, $line);

    if( exists $hash{$q} ) {
        push @{ $hash{$q} }, $seq;
    } 
    else {
        $hash{$q} = [$seq];
    }
}

# print the resulting hash
for my $k ( keys %hash ) {
   print "$k : ", join(', ', @{$hash{$k}}), "\n";
}


# prints
# A : 1, 3, 2
# T : 2, 4
# C : 1, 1, 2
# G : 3, 5
于 2013-07-10T13:30:26.690 回答