1. ホーム
  2. perl

Perl: if ( リストの中の要素 )

2023-09-09 06:28:23

質問

私は、リスト内の要素の存在を探しています。

Pythonでは in というキーワードがあり、私は以下のようなことをします。

if element in list:
    doTask

リスト全体を手動で反復処理することなく、Perlで同等のものがあるのでしょうか?

どのように解決するのですか?

アップデートを行います。

<ブロッククオート

スマートマッチの一連の機能は、現在実験的なものです。

スマートマッチは v5.10.0 で追加され、v5.10.1 で大幅に改訂されましたが、これは定期的に不満が出るポイントでした。スマート マッチが有用である方法はいくつかありますが、Perl のユーザーと実装者の両方にとって問題があり、混乱していることも判明しています。この問題に対処する最善の方法については、これまでにも多くの提案がなされています。しかし、smartmatch が将来的に変化するか消滅することは明らかです。その現在の動作に依存することはお勧めできません。

パーサーが ~~, given, または when を見たときに警告が発行されるようになりました。




Perl v5.10 を必要としないのであれば、以下の例のいずれかを使用することができます。

  • スマートマッチ ~~ 演算子を使用します。

    if( $element ~~ @list ){ ... }
    if( $element ~~ [ 1, 2, 3 ] ){ ... }
    
    
  • また given / when を構築します。これは内部でスマートマッチの機能を使用しています。

    given( $element ){
       when( @list ){ ... }
    }
    
    
  • を使用することもできます。 for ループをトピカライザーとして使うこともできます。 $_ ).

    for( @elements ){
       when( @list ){ ... }
    }
    
    

Perl 5.12 で登場するもののひとつに、修正後バージョンの when . というのは、さらに似ていて ifunless .

given( $element ){
  ... when @list;
}


古いバージョンのPerlで実行できるようにする必要がある場合、まだいくつかの選択肢があります。

  • を使うことで逃げられると思うかもしれません。 リスト::ユーティリティ::最初の を使っても大丈夫だと思うかもしれませんが、いくつかの端境期があり、それが問題になります。

    この例では、マッチングを成功させるために 0 . 残念ながら、このコードでは failure を毎回表示します。

    use List::Util qw'first';
    my $element = 0;
    if( first { $element eq $_ } 0..9 ){
      print "success\n";
    } else {
      print "failure\n";
    }
    
    

    の戻り値を確認することができます。 first にマッチするかどうかを調べることもできますが、これは undef に対するマッチを成功させたい場合は失敗します。

  • を安全に使用することができます。 grep を使っても大丈夫です。

    if( grep { $element eq $_ } 0..9 ){ ... }
    
    

    これは、安全な grep はスカラーコンテキストで呼ばれるからです。配列はスカラーコンテキストで呼び出されると、要素の数を返します。ですから、これはたとえ undef .

  • を囲む for ループを使うことができます。ただ、必ず last を呼び、マッチングに成功したときにループから抜けるようにしてください。さもないと、コードを何度も実行することになるかもしれません。

    for( @array ){
      if( $element eq $_ ){
        ...
        last;
      }
    }
    
    
  • を置くと for の条件内でループさせることができます。 if 文の中でループする ...

    if(
      do{
        my $match = 0;
        for( @list ){
          if( $element eq $_ ){
            $match = 1;
            last;
          }
        }
        $match; # the return value of the do block
      }
    ){
      ...
    }
    
    
  • ...ですが、このように for ループの前に if ステートメントの前にループします。

    my $match = 0;
    for( @list ){
      if( $_ eq $element ){
        $match = 1;
        last;
      }
    }
    
    if( $match ){ ... }
    
    
  • 文字列に対してのみマッチングを行うのであれば、ハッシュを使用することもできます。これは、以下のような場合にプログラムを高速化することができます。 @list が大きい場合 に対してマッチングすることになります。 %hash と何度もマッチします。特に @array が変化しない場合は特にそうです。 %hash を一度読み込むだけだからです。

    my %hash = map { $_, 1 } @array;
    if( $hash{ $element } ){ ... }
    
    
  • 自分でサブルーチンを作ることもできます。このような場合、便利なのが プロトタイプ .

    sub in(&@){
      local $_;
      my $code = shift;
      for( @_ ){ # sets $_
        if( $code->() ){
          return 1;
        }
      }
      return 0;
    }
    
    if( in { $element eq $_ } @list ){ ... }