Perl:单个grep操作与单个for循环相同吗?

时间:2014-03-07 11:24:45

标签: perl for-loop grep

说我有一个以下的现有代码。

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足以赢得单次迭代?我将在重返工作岗位时尝试基准测试。

2 个答案:

答案 0 :(得分:3)

一般来说,像grep这样的inbuilts会比手动循环更快。

然而,在您的特定情况下,有几个陷阱:

  1. 这两个代码示例不做同样的事情。在第一种情况下,如果条件匹配多次,则可以多次调用这些函数。在第二个例子中,函数最多可以被调用一次。

  2. 在循环或grep,map等中使用/ $ foo /等表达式会导致每次都编译正则表达式。

  3. 由于您没有锚定正则表达式,因此也可能发生部分匹配。

  4. 我会使用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) : '';