3

ハッシュがある場合

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

これを行う最も簡単な方法は何ですか?

4

5 に答える 5

7

List::MoreUtilsanyには、と同様の構文を使用する関数が呼び出されますgrepが、基準が最初に満たされたときに内部ループが停止します。この動作の利点は、必要な反復がはるかに少なくなることです (交差点のランダムな分布を想定)。

の追加の利点は、anyコードの明快さです。それは、その機能にちなんで名付けられています。Perl のベスト プラクティスgrepでは、ブール コンテキストでの使用を推奨していませんgrepanyこれはブール値のコンテキストで機能しますが、コードの意図は、ブール値の使用のために特別に設計された よりも読者にとって明確ではありません。

anyList::MoreUtils に依存関係を追加するのは事実です。ただし、List::MoreUtils は非常に遍在するモジュールの 1 つであり、既にインストールされている可能性が高いです。

次に例を示します。

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;

もう 1 つのオプションは、Perl 5.10.0 以降で使用可能になった~~ Smart Match Operatorです。次のように使用できます。

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;

smartmatch を使用すると、最小限の Perl バージョンの依存関係を優先して、List::MoreUtils の依存関係を排除できます。コードが のように明確かどうかを判断するのはあなた次第ですany

于 2012-06-11T01:28:54.510 に答える
5

grep良いアイデアであり、おそらく最もクリーンです。ただし、論理 OR 代入演算子||=も使用できます。

my $found;
$found ||= exists $foo{$_} for @cmp1;
于 2012-06-11T00:59:52.820 に答える
5

これを記述する最も適切な方法は、演算子grepと一緒に使用することです。exists

このコード

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
于 2012-06-11T00:42:23.317 に答える
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
于 2012-06-11T08:45:55.233 に答える
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'.
于 2012-06-11T00:16:11.827 に答える