我需要一个有效的commify过滤器或例程来与Template :: Toolkit一起使用。它将在页面上多次使用。它应该支持小数。
这个可以在The Perl Cookbook找到:
sub commify {
my $text = reverse $_[0];
$text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
return scalar reverse $text;
}
有更有效的方法吗?
答案 0 :(得分:8)
在尝试优化任何内容之前,请确保它确实存在问题。使用分析器查找代码中的问题区域并关注这些区域。
commify解决方案与您可以获得的一样好,但如果您需要绕过它,还有其他一些事情可以做:
答案 1 :(得分:4)
我认为,如果你担心速度这个问题 - 你会严重错误地担心你的担忧。
commify功能在我的桌面上每秒运行130000次,如:“31243245356.4432”。
这意味着如果您的页面上有10000个数字,那么它的通信将需要76毫秒。并且页面的模板工具包处理可能需要2-3倍的时间。
答案 2 :(得分:4)
另一种选择是:
sub commify {
my $text = shift;
1 while $text =~ s/ ( \d ) ( \d{3} ) (\D|\z) /$1,$2$3/xms;
return $text;
}
当决定哪个更快时,Benchmark模块非常有用。
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark;
sub your_commify {
my $text = reverse 100000000;
$text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
return scalar reverse $text;
}
sub my_commify {
my $text = 100000000;
1 while $text =~ s/ ( \d ) ( \d{3} ) (\D|\z) /$1,$2$3/xms;
return $text;
}
timethese(
-10,
{
'yours' => \&your_commify,
'mine' => \&my_commify,
}
);
运行此命令:
~$ ./benchmark.pl
Benchmark: running mine, yours for at least 10 CPU seconds...
mine: 10 wallclock secs (10.01 usr + 0.01 sys = 10.02 CPU) @ 111456.89/s (n=1116798)
yours: 11 wallclock secs (10.04 usr + 0.00 sys = 10.04 CPU) @ 250092.33/s (n=2510927)
看起来你的速度快〜2.25倍! (当使用“至少10 CPU秒”模式时,您必须检查使用的“n”值。)
所以看起来你必须继续搜索......但请记住使用Benchmark!
答案 3 :(得分:3)
sub commify {
my $n = $_[0];
my $s = abs($n) != $n;
my $x = index($n, '.');
$x = length($n) if $x == -1;
substr($n, $x, 0, ',') while ($x -= 3) > $s;
return $n;
}
答案 4 :(得分:2)
我同意brian和depesz:从实际的角度来看,如果你试图提高应用程序的性能,这个功能可能不是开始的地方。也就是说,可以编写更快的commify
函数。一种方法是避免正则表达式。
use strict;
use warnings;
use Benchmark qw(cmpthese);
sub commify_regex {
my $text = reverse $_[0];
$text =~ s{(\d\d\d)(?=\d)(?!\d*\.)}{$1,}g;
return scalar reverse $text;
}
sub commify_substr {
my $v = $_[0];
my $len = length $v;
my $dec = index($v, '.');
my $i = 3 + ($dec < 0 ? 0 : $len - $dec);
$len -- unless $v == abs($v);
while ($i < $len ++){
substr($v, -$i, 0, ',');
$i += 4;
}
return $v;
}
my @tests = qw(
1 12 123 1234 12345 123456 1234567
12345678 123456789 1234567890 12345678901
123456789012 1234567890123
);
push @tests, map "$_.$_", @tests;
push @tests, map - $_, @tests;
for my $t (@tests){
print "Incorrect for: ", $t, "\n"
unless commify_substr($t) eq commify_regex($t);
}
cmpthese( -2, {
regex => sub { commify_regex($_) for @tests },
substr => sub { commify_substr($_) for @tests },
});
# Output on my Windows machine.
Rate regex substr
regex 3277/s -- -54%
substr 7109/s 117% --
答案 5 :(得分:2)
这可以使用单个正则表达式完成:
$number =~ s/(?<=\d)(?=(?:\d\d\d)+(?!\d))/,/g;