Perl判断变量元素是否存在于数组列表中
2013-10-31 16:47:21 阿炯

需要判断一个变量存在于列表变量中,总结了可用的方法。
perl中并没有'in'之类的函数,但可以考虑使用'grep'函数来实现。
if( grep { $element eq $_ } 0..9 ){ ... }
if (grep { $_ eq $element } @list) {....}

当然也可以用原生的循环来实现。
for( @array ){
 if( $element eq $_ ){
  ...
  last;
 }
}

也可以借用do块来快速实现目的。
if(
 do{
  my $match = 0;
  for( @list ){
   if( $element eq $_ ){$match = 1;last;}
  }
 $match; # the return value of the do block
 }
){ ... }

使用map进行hash化操作。
my %hash = map { $_, 1 } @array;
if( $hash{ $element } ){ ... }
if ( exists $lookup{ $element }){...}

使用原型函数来实现。
sub in(&@){
 local $_;
 my $code = shift;
 for( @_ ){ # sets $_
  if( $code->() ){
   return 1;
  }
 }
 return 0;
}
if(in{$element eq $_} @list ){ ... }

sub is (&@) {
 my $test = shift;
 $test->() and return 1 for @_;
 0
}

sub in (@) {@_}
if( is {$_ eq "a"} in qw(d c b a) ) {
 print "Welcome in perl!\n";
}

List系列模块中就对列表操作提供了接口,可以使用它们中的一些函数来实现。
use List::Util qw'first';
my $element = 7;
if( first { $element eq $_ } 0..9 ){
  print "success\n";
} else {
  print "failure\n";
}

$foo = first { ($_ && $_ eq "value" } @list;

use List::MoreUtils qw(any);
my $value = 'test'; # or any other scalar
my @array = (1, 2, undef, 'test', 5, 6);
no warnings 'uninitialized';

if ( any { $_ eq $value } @array ) {
 print "$value present\n"
}

它的调用方式有下面几种:
if any(@ingredients) eq 'flour';

if @ingredients->contains('flour');

在新版本的Perl(5.10及以上)还可以使用它们的新特性来实现此类操作。
智能匹配 smart match ~~ operator.
if( $element ~~ @list ){ ... }
if( $element ~~ [ 1, 2, 3 ] ){ ... }

使用given/when控制结构
在when语句内还是使用了智能匹配。
given( $element ){
   when( @list ){ ... }
}

关于上述方法的评价:
Don't use the first() function! It doesn't express the intent of your code at all. Don't use the "Smart match" operator: it is broken. And don't use grep() nor the solution with a hash: they iterate through the whole list. While any() will stop as soon as it finds your value.

参考来源:
http://www.freeoa.net/development/perl/perl-grep-fun_1843.html

http://www.freeoa.net/development/perl/comprehend-perl-grep_1850.html

http://stackoverflow.com/questions/2383505/perl-if-element-in-list

http://blogs.perl.org/users/mascip/2013/05/the-clearest-ways-to-check-if-a-list-contains.html