我对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语句变得非常长并且包含在几行上。
感谢任何帮助!
答案 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::Util
有any
运算符。但是,要非常小心。 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) {...
这对你有用吗?