我有一个关于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 语句变得相当长并且换行在几行上。
任何帮助不胜感激!
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/;
一个想法。
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
) {
}
这对于智能匹配来说是一个很好的工作,但是运算符已被标记为实验性,可能会从更高版本的 Perl 中删除。
List::Util
具有any
运算符。但是,要非常小心。List::Util
是至少从Perl 5.8.8开始的标准Perl模块。不幸的是,不包括漂亮的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" ... ) {
如果您决定更改有效的值列表,则必须浏览整个程序才能搜索它们。这就是为什么我把它们变成一个常数。程序中只有一个地方必须修改它们。
有许多选项(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}) { ... }
如果您使用的是 Perl 5.10 或更高版本,则可以使用智能匹配运算符:
if ($mode ~~ ['one', 'two', 'three'])
如果要检查很多很多组合,请考虑将$mode转换为编号位:
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) {...
这对你有用吗?