在Perl中分裂很长音译的效率

时间:2013-11-06 00:56:17

标签: performance perl processing-efficiency transliteration

我有这么长的音译:

$text =~ tr/áàăâǎåǻäǟãȧǡąāȁȃɑʙƀɓƃćĉčċçȼƈɕʗďđðɖɗƌȡéèĕêěëėȩęēȅȇɇɛ/aaaaaaaaaaaaaaaaabbbbcccccccccdddddddeeeee/;
# Etc. (About 400 chars)

我想将其分成几个音译,因为生成的代码更容易维护:

$text =~ tr/áàăâǎåǻäǟãȧǡąāȁȃɑ/aaaaaaaaaaaaaaaaa/;
$text =~ tr/ʙƀɓƃ/bbbb/;
$text =~ tr/ćĉčċçȼƈɕʗ/ccccccccc/;
# Etc.

我相信这会让事情变得缓慢,但我想肯定地知道。这个过程在非常繁忙的服务器上每秒运行大约1000次。

感谢。

3 个答案:

答案 0 :(得分:7)

你可以建立一个音译员:

my %translits = (
   'áàăâǎåǻäǟãȧǡąāȁȃɑ' => 'a',
   'ʙƀɓƃ'              => 'b',
   'ćĉčċçȼƈɕʗ'         => 'c',
);

my $pat  = '';
my $repl = '';
for (keys(%translit)) {
   $pat  .= $_;
   $repl .= $translit{$_} x length($_);
}

my $tr1 = eval "sub { tr/\Q$pat\E/\Q$repl\E/ }" or die $@;
   -or-
my $tr2 = eval "sub { \$_[0] =~ tr/\Q$pat\E/\Q$repl\E/ }" or die $@;

然后像这样使用它:

$tr1->() for $str;
   -or-
$tr2->($str);

当然,您可以随时使用Text::Unidecode

答案 1 :(得分:4)

我希望第二个解决方案有三个操作速度较慢,因为它会重新扫描$text中已被替换的字符。

答案 2 :(得分:2)

这是一个基准:

use Benchmark qw(:all);

my $str = 'áàăâǎåǻäǟãȧǡąāȁȃɑʙƀɓƃćĉčċçȼƈɕʗďđðɖɗƌȡéèĕêěëėȩęēȅȇɇɛ/aaaaaaaaaaaaaaaaabbbbcccccccccdddddddeeeee';
my $count = -2;
cmpthese($count, {
    'one tr' => sub {
        $str =~ tr/áàăâǎåǻäǟãȧǡąāȁȃɑʙƀɓƃćĉčċçȼƈɕʗďđðɖɗƌȡéèĕêěëėȩęēȅȇɇɛ/aaaaaaaaaaaaaaaaabbbbcccccccccdddddddeeeee/;
    },
    'multi tr' => sub {
        $str =~ tr/áàăâǎåǻäǟãȧǡąāȁȃɑ/aaaaaaaaaaaaaaaaa/;
        $str =~ tr/ʙƀɓƃ/bbbb/;
        $str =~ tr/ćĉčċçȼƈɕʗ/ccccccccc/;
        $str =~ tr/ďđðɖɗƌȡ/ddddddd/;
        $str =~ tr/éèĕêěëėȩęēȅȇɇɛ/eeeee/;
    },
});

<强>结果:

              Rate multi tr   one tr
multi tr 1215538/s       --     -81%
one tr   6271883/s     416%       --

正如我们所见,一个tr比multi-tr快5倍。