如何在数组元素中搜索哈希键中的匹配项

时间:2013-05-16 10:52:32

标签: arrays perl hash

我有一个数组,其中包含DNA序列的唯一ID(数字)。我把我的DNA序列放在哈希中,这样每个键都包含一个描述性的标题,它的值就是DNA序列。此列表中的每个标头都包含基因信息,并以其唯一ID号作为后缀:

唯一ID:14272

标题(散列键):PREDICTEDXenopusSiluranatropicalishypotheticalproteinLOCLOCmRNA14272

序列(哈希值):ATGGGTC ......

我想遍历每个唯一ID并查看它是否与每个标头末尾的数字(散列键)匹配,如果是,则将散列键+值打印到文件中。到目前为止,我有这个:

my %hash; 
@hash{@hash_index} = @hash_seq;

foreach $hash_index (sort keys %hash) {
        for ($i=0; $i <= $#scaffoldnames; $i++) {
            if ($hash_index =~ /$scaffoldnames[$i]/) {
                print GENE_ID "$hash_index\n$hash{$hash_index}\n";
        }
    }
}
close(GENE_ID);

其中唯一ID包含在@scaffoldnames中。

这不起作用!我不确定如何最好地遍历散列和数组以找到匹配。


我将在下面展开:

上游代码:

foreach(@scaffoldnames) {
     s/[^0-9]*//g;
} #Remove all non-numerics

my @genes = read_file('splice.txt'); #Splice.txt is a fasta file

my $hash_index = '';
my $hash_seq = '';
foreach(@genes){
    if (/^>/){
        my $head = $_;
        $hash_index .= $head; #Collect all heads for hash
    }
        else {
            my $sequence = $_;
            $hash_seq .= $sequence; #Collect all sequences for hash
        }
}

my @hash_index = split(/\n/,$hash_index); #element[0]=head1, element[1]=head2
my @hash_seq = split(/\n/, $hash_seq); #element[0]=seq1, element[1]=seq2

my %hash; # Make hash from both arrays - heads as keys, seqs as values
@hash{@hash_index} = @hash_seq;

foreach $hash_index (sort keys %hash) {
        for ($i=0; $i <= $#scaffoldnames; $i++) {
            if ($hash_index =~ /$scaffoldnames[$i]$/) {
                print GENE_ID "$hash_index\n$hash{$hash_index}\n";
        }
    }
}
close(GENE_ID);

我试图分离由cuffdiff(RNA-Seq)输出的所有不同表达的基因(通过唯一ID),并将它们与它们来自的支架(在这种情况下表达的序列)相关联。

因此我希望我可以隔离每个唯一ID并搜索原始的fasta文件,以提取它匹配的标头及其关联的序列。

1 个答案:

答案 0 :(得分:4)

您似乎错过了哈希点:它们习惯于按键索引您的数据,这样您就可以一步访问相关信息,就像使用数组一样。循环遍历每个哈希元素都会破坏这一点。例如,你不会写

my $value;

for my $i (0 .. $#data) {
  $value = $data[i] if $i == 5;
}

你只需要这样做

my $value = $data[5];

如果没有更多关于您的信息来源的信息以及您想要的确切内容,很难提供帮助,但此代码应该有所帮助。

我使用了单元素数组,我认为它看起来就像你正在使用的那样,并使用ID构建了一个哈希,它将两个标题和序列索引为一个双元素数组(标题的尾随数字)作为键。您可以使用14272查找ID $hash{14272}的信息。标头为$hash{14272}[0],序列为$hash{14272}[1]

如果您提供更多有关您情况的指示,我们可以为您提供进一步的帮助。

use strict;
use warnings;

my @hash_index = ('PREDICTEDXenopusSiluranatropicalishypotheticalproteinLOCLOCmRNA14272');
my @hash_seq = ('ATGGGTC...');

my @scaffoldnames = (14272);

my %hash = map {
  my ($key) = $hash_index[$_] =~ /(\d+)\z/;
  $key => [ $hash_index[$_], $hash_seq[$_] ];
} 0 .. $#hash_index;

open my $gene_fh, '>', 'gene_id.txt' or die $!;

for my $name (@scaffoldnames) {
  next unless my $info = $hash{$name};
  printf $gene_fh "%s\n%s\n", @$info;
}

close $gene_fh;

<强>更新

从您发布的新代码看起来您​​可以使用此代码替换该部分。

它的工作原理是从它找到的每个序列头中获取尾随数字,并使用它作为键来选择要附加数据的哈希元素。哈希值是标题和序列,都在一个字符串中。如果您有理由将它们分开,请告诉我。

foreach (@scaffoldnames) {
    s/\D+//g;
}    # Remove all non-numerics

open my $splice_fh, '<', 'splice.txt' or die $!;    # splice.txt is a FASTA file

my %sequences;

my $id;
while (<$splice_fh>) {
    ($id) = /(\d+)$/ if /^>/;
    $sequences{$id} .= $_ if $id;
}

for my $id (@scaffoldnames) {
    if (my $sequence = $sequences{$id}) {
        print GENE_ID $sequence;
    }
}