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 メソッドは非常に遅く、1 秒あたり 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 分であるのに対し、1 秒もかからずに終了しました。

それが役立つことを願っています。

于 2012-12-11T17:58:57.113 に答える
1

ある文字を別の文字に単純に置き換える場合 (文字単位または文字列単位ではありません$str =~ tr/X/A/;!!!)、文字変換の方が高速です: 複雑な正規表現パターンが必要な場合は、Perl のre::engine::RE2の使用を検討してください。 Google RE2 エンジンのバインディング。これは、複雑な正規表現の場合にのみ高速であることに注意してください。

于 2012-12-11T17:09:04.360 に答える