说我有一个以下的现有代码。
my $names = &loadNames(); # No duplicate names
my $u1;
my $u2;
for (my $i = 0 ; $i < @$names; $i++) {
if($$names[$i] eq $input_one){
$u1 = loadUserFromOneSource($input_one);
}
if($$names[$i] eq $input_two){
$u2 = loadUserFromSecondSource($input_two);
}
}
现在,如果我重构上面的代码,如下所示
my $names = &loadNames(); #Returns array reference
my $u1 = grep $_ eq $input_one, @$names;
my $u2 = grep $_ eq $input_two, @$names;
$u1 = loadUserFromOneSource($u1) if $u1;
$u2 = loadUserFromSecondSource($u2) if $u2;
我真的改善了什么吗?或者我做得更糟,因为我在同一个列表上运行两个greps。
澄清: 提出问题的唯一目的是了解grep和循环之间的性能权衡。在这两种情况下,我都会提取出两个名字。但是在单个迭代中的第一个例子中。第二个例子是两个greps完成的。我在第二种方法中的成本是否翻了一倍?或者grep足以赢得单次迭代?我将在重返工作岗位时尝试基准测试。
答案 0 :(得分:3)
一般来说,像grep这样的inbuilts会比手动循环更快。
然而,在您的特定情况下,有几个陷阱:
这两个代码示例不做同样的事情。在第一种情况下,如果条件匹配多次,则可以多次调用这些函数。在第二个例子中,函数最多可以被调用一次。
在循环或grep,map等中使用/ $ foo /等表达式会导致每次都编译正则表达式。
由于您没有锚定正则表达式,因此也可能发生部分匹配。
我会使用grep但是将条件更改为
my $u1 = grep $_ eq $input_one, @$names;
答案 1 :(得分:2)
首先,您不再在新代码中测试相等性,而是包含正则表达式。这可能会引入一个错误。
另一个解决方案是将数组转换为哈希,以便您可以测试名称是否存在。即perldoc How can I tell whether a certain element is contained in a list or array?
my $names = loadNames(); #Returns array reference
my %hasName = map {$_ => 1} @$names;
my $u1 = $hasName{$input_one} ? loadUserFromOneSource($input_one) : '';
my $u2 = $hasName{$input_two} ? loadUserFromSecondSource($input_two) : '';