Perl中的慢循环

use*_*545 5 perl performance loops

以下子程序在我的计算机中需要12秒才能执行:

sub trans() {   
    $trans = "";
    foreach $nuc (@array) {
        foreach $k (keys %hash) {
            if ($nuc eq $k) {
                $w = $hash{$k};
                $trans .= $w;
                last;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

代码继续生成内容为$ trans的文件.正如我所说,这需要12秒.问题是我必须生成256个输出文件......这需要太长时间.....

任何优化它的想法?

Eev*_*vee 11

为什么循环遍历哈希中的每个键只是为了测试它是否等于已知值?

sub trans() {   
    $trans = "";
    for my $nuc (@array) {
        if (exists $hash{$nuc}) {
            $trans .= $hash{$nuc};
        }
    }
    return $trans;
}
Run Code Online (Sandbox Code Playgroud)

但那么......为什么还要费心去测试.

sub trans() {   
    $trans = "";
    for my $nuc (@array) {
        $trans .= $hash{$nuc} // "";
    }
    return $trans;
}
Run Code Online (Sandbox Code Playgroud)

谁还需要循环呢?

sub trans() {   
    return join '', map { $hash{$_} // '' } @array;
}
Run Code Online (Sandbox Code Playgroud)

  • @jkshah:`//`是'defined-or'运算符.如果左侧评估为假,则返回右侧.请参阅[`perldoc perlop`](http://perldoc.perl.org/perlop.html#Logical-Defined-Or)了解更多信息 (2认同)
  • 以上评论中的更正:"如果左侧评估为__undefined__" (2认同)

Dav*_*man 6

另一种方法是使用哈希切片:

sub trans() {   
  return join '', @hash{@array};
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果@array包含的值不是现有键%hash并且已warnings启用,则会抱怨未初始化的值.(你已经warnings启用了,不是吗?)根据您的数据的规则,这可能是一个错误(在这种情况下加入no warningssub会解决这个问题),或者一个特征.


Dav*_*ang 4

尝试以下操作

sub trans() {   
    $trans = "";
    foreach $nuc (@array) {
            if ($hash{$nuc}) {
                $w = $hash{$nuc};
                $trans .= $w;
            }

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你好,原因是在这个问题中,我们对数组的每个项目迭代了哈希的所有键,其复杂度为 O(键数),在结果中我们直接检查哈希,其复杂度为 O( 1)。有关其工作原理的更多信息,请查看 https://en.wikipedia.org/wiki/Hash_table (2认同)