作者chong (CW)
看板Perl
标题[问题] 执行效率
时间Fri Mar 28 17:09:14 2014
请问各位,我现在有一笔约10万笔基因序列的资料,
部分内容如下:
>Locus_41_Transcript_1/7_Confidence_0.385_Length_892
>Locus_41_Transcript_2/7_Confidence_0.385_Length_920
>Locus_41_Transcript_3/7_Confidence_0.577_Length_1466
>Locus_41_Transcript_4/7_Confidence_0.577_Length_1431
>Locus_41_Transcript_5/7_Confidence_0.538_Length_1359
>Locus_41_Transcript_6/7_Confidence_0.577_Length_1431
>Locus_41_Transcript_7/7_Confidence_0.577_Length_1431
>Locus_42_Transcript_1/1_Confidence_1.000_Length_2058
>Locus_43_Transcript_1/10_Confidence_0.312_Length_1094
>Locus_43_Transcript_2/10_Confidence_0.469_Length_1565
以locus_41为例,它有7笔资料,最後的数字是该序列的长度,
像这样的资料,我只要取长度最大的一笔。
若是locus_42,因为只有一笔,所以不用取舍,直接使用。
我写的程式码如下:
#!/usr/bin/env -perl -w
use Bio::DB::Fasta;
open my $query, "<", $ARGV[0] or die "$!";
my (%query_hash, %whole);
while (my $line = <$query>) {
chomp ($line);
if ($line =~ /^>/) {
my @line = split (/_/, $line);
my $name = substr($line[0], 1)."_$line[1]";
$whole{substr($line, 1)} = "$name $line[7]";
#把所有内容皆读入hash。
if (! exists $query_hash{$name}) {
$query_hash{$name} = $line[7];
}
elsif ($query_hash{$name} <= $line[7]) {
$query_hash{$name} = $line[7];
#保留数字最大的一笔
}
}
}
close $query;
my $db = Bio::DB::Fasta->new($ARGV[1]);
my @query_hash_result;
foreach my $result (keys %query_hash) {
my $query_whole = "$result $query_hash{$result}";
while (my ($key, $value) = each (%whole)) {
if ($value eq $query_whole) {
#重新取得完整的标题,用以取得DNA序列资料。
my $query_fasta = $db->get_Seq_by_id($key);
my $query_seq = $query_fasta->seq;
print ">$query_fasta\n";
print "$query_seq\n";
}
}
}
现在遇到的状况是,如果我只执行上半部的程式码,即把标题资料读入hash,
没什麽问题,不会用很多时间。
在%query_hash里,大约会取得7万笔资料。
而%whole里,大约有14万笔资料。
但,当我把2个hash放在一起比较,要取回完整的标题时,
整个执行的速度慢了相当多!
请问是不是我写的程式码里有问题?应该要怎麽修改会比较好?
谢谢
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 140.116.25.64
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/Perl/M.1395997757.A.123.html
1F:推 LiloHuang:由於第二个 while loop 会将整个 %whole 都拜访一次 03/28 17:54
2F:推 LiloHuang:当 %whole 很大时,时间复杂度会大幅度的提高 03/28 17:54
3F:→ LiloHuang:如果只是需要把完整标题拿出来,可以考虑多记忆一些内容 03/28 17:55
4F:→ LiloHuang:例如改成 $query_hash{$name} = [最大数, 完整的一行]; 03/28 17:56
5F:→ LiloHuang:这样在跑第二个回圈时,就不需要对 %whole 从头查到尾 03/28 17:57
6F:推 LiloHuang:或者把每一行的内容放在单独的 array 里面 03/28 18:04
7F:→ LiloHuang:$query_hash{$name} = [最大数, 完整资料的索引]; 03/28 18:05
8F:→ chong:谢谢你的建议,我再尝试看看。 03/28 21:57
9F:推 rkcity:是Lilo大!! (膜拜 03/29 17:13
10F:→ chong:速度差非常多,旧的用了数小时,新的瞬间秒杀! 03/31 11:10
11F:→ hhs66317:Lilo的思路值得学习﹐赞~~ 06/01 10:09