虽然你已经得到了完整的解释,但我忍不住重写了
一个简单的例子
use warnings;
use strict;
use List::Util qw(sum0);
my $y = ...
my @M = $y =~ /.../;
my ($best, $bestseq) = (0, '');
foreach my $m (@M) {
(my $new_m = $m) =~ s/\d+://g;
my @w = split ' ', $new_m; # CHANGED from original
my $v = sum0 grep { /^\d+$/ } @w;
if ($v > $best) {
$best = $v;
$bestseq = $new_m;
}
}
sub length_in_words {
return scalar split ' ', $_[0];
}
循环似乎执行以下操作。 @M 数组的每个元素都被\d+:(连续的数字后跟:)剪除,然后拆分为单词。所有仅是数字的单词都被汇总。这用于找到最大(“最佳”)此类总和并记录其元素。
一些cmets
-
一个foreach别名数组元素正在处理中,所以如果操作改变了当前处理的元素,那么数组也会改变。
原始代码不会更改@M 的元素,所以我首先将$m 复制到$new_m 中并使用它。如果这无关紧要并且@M 可能会在此循环中更改,则只需执行$m =~ s/\d+://g;,并在其他地方使用$m 而不是$new_m。
-
index $i 没有被使用,所以直接遍历数组元素
-
$z 未使用,已删除
-
map 总结了@m 元素的过滤(仅数字)子集
-
原始“最佳”初始化为零,因此使用sum0,它在空列表输入时给出零
-
原始split / /, $m 将标量$m 拆分为单个 空格。我强烈怀疑其意图是将$m 解析为单词,因此被所有连续的空格分割。因此我使用
my @w = split ' ', $new_m;
其中' ' 是一种特殊模式,它可以按任意数量的空格进行分割,并且还会删除前导和尾随空格。见split。我将它重命名为@w,因为它显然是单词。
还有一条评论:我会使用@words、$val(或类似的)而不是一个字母的名称。
对length_in_words()中使用的代码和效率的评论。
当然,有多种方法可以计算字符串中的单词数。下面的基准显示了此处选择的速度最快的基准
use warnings;
use strict;
use feature 'say';
use Benchmark 'cmpthese';
my $run_for = shift // 3; # seconds for each
my $text = " ah\n no \t hi end ";
sub split_scalar {
return scalar split ' ', $_[0];
}
sub regex_context {
my $wc =()= $_[0] =~ /\S+/g;
}
sub regex_while {
my $wc;
++$wc while $_[0] =~ /\S+/g;
return $wc;
}
cmpthese (-$run_for, {
split_scalar => sub { split_scalar($text) },
regex_context => sub { regex_context($text) },
regex_while => sub { regex_while($text) },
});
在 v5.24.4 下,在不错的桌面上打印
率 regex_context regex_while split_scalar
正则表达式_上下文 1119833/s -- -7% -90%
regex_while 1203020/s 7% -- -89%
split_scalar 11351365/s 914% 844% --
首先,在标量上下文中使用 split 的巨大优势让我感到惊讶,我猜这是由于 split 中的特定优化,这个用例从中受益。
更有趣的是,当拆分一个包含 10_000 个单词的字符串时,标量拆分方式更加优越——它可以达到 4026 %。
在我的测试中,这表明在该桌面和服务器上重复运行的结果一致,使用 v5.16.3 和 v5.24.4,在旧版 Perl 下有以下细微差别。
在 v5.16 中,split 的优势要小一些(尽管仍然是 7 倍),并且在正则表达式中使用 =()= 的上下文播放并不比分配给数组并返回 @ 更好987654355@ (在 v5.24 中是 30-40%,所以我省略了生成数组变量的情况)。
但是,请注意,在 v5.12 之前,标量上下文中的 split 具有 surprising (nasty) behavior。鉴于问题中的代码,这可能是在较旧的 Perl 上运行(运行?)(什么不能原谅显示的代码),在这种情况下,请使用基于正则表达式的替代方案 split。
感谢melpomene cmets。