2017-02-11 11 views
1

における等価演算子を選択します。そのリストの各項目について動的Iは混合型(文字列や数字)の値のリストを持っているPerlの

my @list = (123, 'foo', 34.5, 'bar', '67baz'); 

を、Iは(均等ランダムタイプの入力と比較する必要があります何かをするために、文字列または数値):両方のオペランドが同じ型(この場合は数字)であるが、警告を上げおよび/または生成されますとき

my $input = 345; 
foreach my $elem (@list) { 
    if ($input == $elem) { 
     # do something 
    } else { 
     # do something else 
    } 
} 

比較(==)が正常に動作します型が不一致のときは間違った結果になります(このコードスニペットでは、s文字列とすることができます。したがって、代わりにeqを使用する必要があります)。

私は、この比較の問題を解決するためのあなたの好みの方法についていくつかの情報を得たいと思います。または、オペランドの型を指定して、適切なタイプの比較を動的に選択(および実行)するモジュールがあるかもしれません。

looks_like_number()からScalar::Utilまでの方法を知っていますが、どのタイプの値を使用しているかを確認するのは良い方法です。前もって感謝します。

+0

'345.0'と' 3.45e2'にマッチさせるには '345'が必要ですか?そうでなければ、常に 'eq'を使うべきです。 – Borodin

答えて

3

多くの言語では、オペランドの型によって操作が決まります。 Perlでは、オペレータがオペレーションを決定し、オペランドが適切なタイプに強制されます。そのため、Perlは、格納されている4つの文字列を、整数として格納された4つ以外の文字列としては考慮しません。彼らは両方とも4です。スカラーが数字か文字列かどうかを調べるコードがあれば、バグコード[1]があります。

あなたが主張するのであれば、の定義を考え出す必要があります。は文字列ではなく数字であると考えられます。 「Perlが数値として使用でき、そうでない場合は文字列」と選択すると、実際にはlooks_like_numberがトリックになります。値がスカラーにどのように格納されるかに基づいて決定することもできますが、スカラーが整数と文字列の両方を持つ場合は、[2]の中で何をすべきかを決める必要があります。

一方、汎用コードを記述しようとしている場合は、関数が(sortのように)比較関数を受け入れることができます。スマートマッチオペレータはバギーとみなされ、それが実験されて停止する前に変更する必要がある理由です

sub find(&@) { 
    my $cb = shift; 
    for (@_) { 
     return 1 if $cb->(); 
    } 

    return 0; 
} 


if (find { $_ == $num_to_find } @nums) { 
    print("Found $num_to_find\n"); 
} else { 
    print("Didn't find $num_to_find\n"); 
} 

find { $_ eq $string_to_find } @strings 

find { $_->year == $year_to_find } @date_time_objects; 

  1. perl -le'open(my $fh, "<", "non-existent"); print 0+$!; print "".$!;'

-4

smartmatch operatorあなたは

no if $] >= 5.018, warnings => qw(experimental::smartmatch); 

my $input = 123; # also works with 34.5, 'foo', etc. 
foreach my $elem (@list) { 
    if ($elem ~~ $input) { 
     # do something 
    } else { 
     # do something else 
    } 
} 

考えを書いてみましょうだろうPerl 6のから採取し、5.10で実装されました。 Perl5.18以降、Perl5に適合するように機能を進化させる方法が議論されているため、インターフェースは「実験的」状態の保留中の変更に格下げされています。

+2

これはむしろ誤解を招いています。彼らはそれをより良いものに進化させようとはしていません。それはバギーで、彼らはそれを修正しようとしている。さらに悪いことに、あなたはそれを修正する必要がある動作に対して特に使用しています。最初にコードを破棄することなく、実験的なステータスを残すことはありません。 – ikegami

3

Sort::Naturallyを使用すると、 'Natural'比較を行うncmp演算子をインポートできます。あなたはこの

use Sort::Naturally; 
if (ncmp($lval, $rval) == 0) { ... } 

を行うことができ平等をチェックするために

はここでどのようにncmpお菓子いくつかのペアのいくつかの例です。

ncmp(1, '1') == 0 
ncmp('a', 'a') == 0 
ncmp('a', 'b') == -1 
ncmp('a', 'A') == -1 
ncmp(2, 1)  == 1 
ncmp(1, 'a') == -1 
ncmp('a', 1) == 1 

基本的には...

0は平等
1あるlvalが少なく、そのrval
-1lvalが大きい、より親切であるrval

0

使用perlのeval文字列、ある手段でありますあなたのプログラム内でミニPerlプログラムを実行することができます(これはスクリプト言語で簡単に行うことができます)。Perl eval ):

# get the var guiding the dynamic operator 
    my $issues_order_by_attribute= $ENV{ 'issues_order_by_attribute' } || 'prio' ; 
    my $operator = '<=>' ; # initialize a default operator 
    # use Scalar::Util looks_like_number method to decide for operator 
    $operator = 'cmp' unless (looks_like_number($issues_order_by_attribute)) ; 
    # use eval string within the code to interpolate the operator 
    # to sort the hash ref of hash refs by the set attribute to order by 
    foreach my $issue_id (
     eval 'sort {  ' . 
      '$hsr2->{$a}->{ $issues_order_by_attribute }' . $operator . '$hsr2->{$b}->{ $issues_order_by_attribute }' . 
      '} keys (%$hsr2)') { 
     # Action !!! 
     my $row = $hsr2->{ $issue_id } ; 
    } 
関連する問題