perl简单的效率和可读性

时间:2013-11-06 21:19:03

标签: perl performance

我对perl的效率和可读性有疑问

我有一个可以采用多个值之一的变量(5-6)。有时我想检查这是否是一个特定的值,有时我想检查它是否是几个选择之一。我在我的代码(在不同的函数中)的许多地方做出这样的决定,我想尽可能“紧凑”。

例如,说

my $mode; # can be any of qw(one two three four five six)
if ($mode eq 'one') {
    #do code
}

if ($mode eq 'one' or $mode eq 'two' or $mode eq 'three') {
    #do more code
}

这当然不是我的真实代码,并且使用有意义的变量名称,我的if语句变得非常长并且包含在几行上。

感谢任何帮助!

6 个答案:

答案 0 :(得分:7)

List::MoreUtils模块具有any功能,就像短路grep

use List::MoreUtils qw/any/;

say "correct mode" if any { $_ eq $mode } qw/one two three/;

那就是说,你仍然可以使用grep,但是它总是测试所有元素,而any在第一个匹配元素之后中止:

say "correct mode" if grep { $_ eq $mode } qw/one two three/;

答案 1 :(得分:3)

一个想法。

my %please_name_me;
$please_name_me{$_}++ for qw(one two three);
if ($please_name_me{$mode}) {
    #do something
}

否则我喜欢使用空格:

if (
    'one' eq $mode or
    'two' eq $mode or
    'three' eq $mode
) {
}

答案 2 :(得分:3)

有许多选项(TMTOWDI)。以下是最简单的两个:

if ($mode =~ /^(?one|two|three)$/) { ... }

if (grep { $mode eq $_ } qw(one two three)) { ... }

事先进行一些设置,您可以提高效率。这样做一次:

 my @modes = qw(one two three);
 my %modes;
 @modes{@modes} = @modes;

然后你的支票变得简单:

if ($modes{$mode}) { ... }

答案 3 :(得分:3)

这对于智能匹配来说是一个不错的工作,但是运算符已被标记为实验性的,可能会从更高版本的Perl中删除。

List::Utilany运算符。但是,要非常小心。 List::Util是标准的Perl模块,因为至少是Perl 5.8.8。不幸的是,不包括好的any运算符。您需要更新此模块才能使用any。但是,first运算符可能足够好并且是程序包的一部分:

use strict;
use warnings;
use feature qw(say);
use autodie;

use List::Util qw(first);

use constant VALID_VALUES => qw(one two three four five);

for my $value ( qw(zero one two three four five six) ) {
    if ( first { $value eq $_ } VALID_VALUES ) {
        say "$value is in the list!";
    }
    else {
        say "Nope. $value is not";
    }
}

由于您的计划中有use List::Util qw(first);,因此用户应该意识到first来自List::Util个包,他们可以使用perldoc List::Util进行查找。

您也可以使用grep而忘记List::Util

for my $value ( qw(zero one two three four five six) ) {
    if ( grep { $value eq $_ } VALID_VALUES ) {
        say "$value is in the list!";
    }
    else {
        say "Nope. $value is not";
    }
}

您不应该使用复杂的正则表达式或if / else链。这些都不一定更清楚,让你的程序更难理解:

if ( $value =~ /^(one|two|three|four|five)$/ ) {

if ( $value eq "one" or $value eq "two" or $value eq "three" ... ) {

如果您决定更改有效的值列表,则必须通过整个程序来搜索它们。这就是我将它们作为常量的原因。程序中只有一个地方需要修改。

答案 4 :(得分:1)

如果您使用的是Perl 5.10或更高版本,则可以使用smart match运算符:

if ($mode ~~ ['one', 'two', 'three'])

答案 5 :(得分:0)

如果要检查许多组合,请考虑将$模式转换为编号位:

if 'one' -> $modeN = 1
if 'two' -> $modeN = 2
if 'three' -> $modeN = 4  etc.

要检查“一个”,if ($modeN == 1) {...

要检查“一个”,“两个”或“三个”,if ($modeN & 7) {...

要检查“两个”或“三个”,if ($modeN & 6) {...

要检查'一个'或('两个'和'三个'),if ($modeN & 1 || &modeN & 6) {...

这对你有用吗?