我有一个由3亿个碱基组成的字符串;
$str = "ATCGTAGCTAGXCTAGCTAGCTGATXXXXATCGTAGCTAGCTGXTGCTAGCXXXXA...A";
我想将字符串中不是[ATGC]的字符替换为其他字符,让我们说“A”,同时获取已被替换字符的位置;
我试过了:
while ($str=~/[^ATGC]/ig)
{
$pos = pos($str);
substr($str, $pos-1,1) = "A";
}
但速度不快。
有谁知道更好的方法吗?
答案 0 :(得分:6)
正则表达式也可以替换匹配。
$str =~ s/X/A/g;
如果你只做一个字符,你甚至可以使用tr
运算符。
$str =~ tr/X/A/g;
甚至可能更快。
答案 1 :(得分:5)
您可以使用search and replace直接使用正则表达式执行替换:
$str =~ s/X/A/ig;
答案 2 :(得分:3)
如有疑问,Benchmark
use strict;
use warnings;
use v5.14;
use Benchmark qw(cmpthese);
my @l = qw(A T G C X);
my $BAR;
$BAR .= $l[rand(@l)] for 1..10000;
cmpthese(-1, {
substr => sub { my $str = $BAR;
while ($str=~/X/ig) {
my $pos = pos($str);
substr($str, $pos-1,1) = "A";
} return $str; },
substitution => sub { my $str = $BAR; $str =~ s/X/A/ig; return $str; },
transliteration => sub { my $str = $BAR; $str =~ tr/xX/aA/; return $str; }});
<强>结果:强>
Rate substr substitution transliteration
substr 55.1/s -- -98% -100%
substitution 2496/s 4433% -- -93%
transliteration 35134/s 63719% 1308% --
正如我们从结果中看到的,对于这个特定的字符串和正则表达式,substr方法确实非常慢,速度为每秒55。使用替换的速度大约快45倍,但这比音译速度快了600倍。
因此,在这种情况下,音译似乎是最快的。这是有道理的,因为它是迄今为止最简单的潜艇。
答案 3 :(得分:2)
如果您只想替换输入字符串中的“X”字符,则可以采用音译方式,并显着提高您的速度。
记录替换字符的位置有点额外的皱纹。我建议如下:
my $huge_string = "GATTACAXX.......";
my $length = length($huge_string);
my $i = 0;
my $output_string;
my @x_positions;
while ($i < $length) {
my $curr_char = substr($huge_string, $i, 1);
if ($curr_char eq "X") {
push (@x_positions, $i);
$output_string .= "A"; # or G, C, T, etc.
} else {
$output_string .= $curr_char;
}
$i++;
}
# do something with $output_string and @x_positions...
我在一个> 1,000,000个字符的测试字符串上运行它,它在不到一秒的时间内完成,而原始代码片段的运行时间约为3分钟。
希望有所帮助。
答案 4 :(得分:1)
如果您只是将一个字符替换为另一个字符(不逐个字符串或逐个字符串!!!),则音译速度更快:$str =~ tr/X/A/;
如果您需要复杂的正则表达式模式,请考虑使用re::engine::RE2,Google RE2 engine的Perl绑定。请注意,复杂正则表达式只会更快。