如何确定数组的元素是否与另一个数组的任何元素匹配?

时间:2012-06-10 23:11:26

标签: perl

如果我有哈希

my %foo = ( foo => 1, bar => 1 );

我想检查%foo中的任何键是否在比较数组中(显然键%foo只是一个数组)。我一直在想一些不存在的奇怪语法,如。

my @cmp0 = qw( foo baz    );
my @cmp1 = qw( baz blargh );

if keys %foo in @cmp0 # returns true because key foo is in the array
if keys %foo in @cmp1 # returns false because no key in foo is an element of cmp1

最简单的方法是什么?

5 个答案:

答案 0 :(得分:7)

List::MoreUtils有一个名为any的函数,它使用类似于grep的语法,但在第一次符合条件时停止其内部循环。这种行为的优点是需要的迭代次数要少得多(假设交叉点的随机分布)。

any的另一个优点是代码清晰度:它以它的功能命名。 Perl最佳实践不鼓励在布尔上下文中使用grep,因为grep的假定用法是返回匹配的元素列表。它在布尔上下文中工作,但代码的意图对于读者来说不如any那么明确,而any是专为布尔使用而设计的。

use List::MoreUtils qw( any ); my %foo = ( foo => 1, bar => 1 ); my @cmp0 = qw( foo baz ); my @cmp1 = qw( baz blargh ); print "\@cmp0 and %foo have an intersection.\n" if any { exists $foo{$_} } @cmp0; print "\@cmp1 and %foo have an intersection.\n" if any { exists $foo{$_} } @cmp1; 确实添加了对List :: MoreUtils的依赖。但是,List :: MoreUtils是无处不在的模块之一,很可能已经安装。

以下是一个例子:

~~

另一个选项是my %foo = ( foo => 1, bar => 1 ); my @cmp0 = qw( foo baz ); my @cmp1 = qw( baz blargh ); print "\@cmp0 and %foo have an intersection.\n" if @cmp0 ~~ %foo; print "\@cmp1 and %foo have an intersection.\n" if @cmp1 ~~ %foo; Smart Match Operator,它在Perl 5.10.0和更新版本中可用。它可以像这样使用:

any

使用smartmatch,您可以消除List :: MoreUtils依赖关系,转而支持最小的Perl版本依赖关系。您可以自行决定代码是否与{{1}}一样清晰。

答案 1 :(得分:5)

最简单的方法是将grepexists运算符一起使用。

此代码

my %foo = ( foo => 1, bar => 1 );

my @cmp0 = qw( foo baz    );
my @cmp1 = qw( baz blargh );

print "YES 0\n" if grep { exists $foo{$_} } @cmp0;
print "YES 1\n" if grep { exists $foo{$_} } @cmp1;

给出了这个输出

YES 0

答案 2 :(得分:5)

grep是一个好主意,可能是最干净的。但是,您也可以使用logical OR assignment operator ||=

my $found;
$found ||= exists $foo{$_} for @cmp1;

答案 3 :(得分:1)

这些是简单的设置操作

use strictures;
use Set::Scalar qw();
⋮
my $foo = Set::Scalar->new(keys %foo);
$foo->intersection(Set::Scalar->new(@cmp0))->size; # 1
$foo->intersection(Set::Scalar->new(@cmp1))->size; # 0

答案 4 :(得分:0)

有 - 像往常一样 - 有更多方法可以解决这个问题。你可以这样做:

#!/usr/bin/perl

use strict ;
use warnings ;

my %hash = ( foo => 1 , bar => 1 ) ;
my %cmp = ( cmp0 => [ qw(foo baz) ] ,
            cmp1 => [ qw(baz blargh) ] ) ;

my @hash_keys = keys %hash ;
foreach my $compare ( keys %cmp ) {
  my %tmp ;
  # Generate a temporary hash from comparison keys via hash slice
  @tmp{@{$cmp{$compare}}} = undef ;
  INNER:
  foreach my $hash_key ( @hash_keys ) {
    if( exists $tmp{$hash_key} ) {
      printf "Key '%s' is part of '%s'.\n" , $hash_key , $compare ;
      last INNER ;
    }
  }
}

这给出了:

Key 'foo' is part of 'cmp0'.
相关问题