2

我有一个由 3 亿个碱基组成的字符串;

$str = "ATCGTAGCTAGXCTAGCTAGCTGATXXXXATCGTAGCTAGCTGXTGCTAGCXXXXA...A";

我想将字符串中不是[ATGC]的字符替换为其他字符,比如说“A”,同时获取已替换字符的位置;

我试过这个:

while ($str=~/[^ATGC]/ig)
{
  $pos = pos($str);
  substr($str, $pos-1,1) = "A";
}

但是速度不好。

有谁知道更好的方法来做到这一点?

4

5 回答 5

6

正则表达式也可以替换和匹配。

$str =~ s/X/A/g;

如果你只做一个字符,你甚至可以使用tr操作符。

$str =~ tr/X/A/g;

这甚至可能更快。

于 2012-12-11T17:05:52.150 回答
5

您可以使用搜索和替换直接使用正则表达式执行替换

$str =~ s/X/A/ig;
于 2012-12-11T17:05:13.260 回答
3

如有疑问,基准

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 倍的音译相比相形见绌。

因此,在这种情况下,音译似乎是最快的。这是有道理的,因为它是迄今为止最简单的潜艇。

于 2012-12-11T17:36:25.173 回答
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 分钟。

希望有帮助。

于 2012-12-11T17:58:57.113 回答
1

如果您只是用另一个字符替换一个字符(不是逐个字符串或逐个字符串!!!),音译会更快:$str =~ tr/X/A/; 如果您需要复杂的正则表达式模式,请考虑使用re::engine::RE2,一个 Perl为Google RE2 引擎绑定。请注意,这仅对于复杂的正则表达式更快。

于 2012-12-11T17:09:04.360 回答