在Perl

时间:2017-02-11 18:47:19

标签: perl comparison operators

我有一个混合类型(字符串和数字)的值列表:

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

对于该列表中的每个项目,我需要与同等随机类型(字符串或数字)的输入进行比较以执行某些操作:

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

当两个操作数具有相同的类型(在这种情况下是数字)时,比较(==)将正常工作,但是当类型不匹配时会引发警告和/或产生错误的结果(对于这段代码片段可以是字符串与数字,也可以是字符串,因此需要使用eq

我想了解一下您解决此比较问题的首选方法。或者,如果有一个模块可以根据操作数的类型动态选择(并执行)正确的比较类型。

我清楚知道一些方法,例如使用looks_like_number()中的Scalar::Util来检查您正在使用的价值类型,但我们认为可能有更好的方法弄清楚如何进行比较。提前谢谢。

4 个答案:

答案 0 :(得分:3)

在许多语言中,操作数的类型决定了操作。在Perl中,运算符确定操作,操作数将被强制转换为正确的类型。因此,Perl并不认为四个存储为不同于四个存储为整数的字符串;他们都是四个人。如果你有代码试图弄清楚标量是数字还是字符串,你就会有错误的代码 [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. 这就是为什么smartmatch操作员被认为是错误的,需要在它停止实验之前进行更改。

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

答案 1 :(得分:3)

您可以使用Sort::Naturally导入执行“自然”比较的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少于-1 lval表示rval大于{{1}}

答案 2 :(得分: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 } ;
    }

答案 3 :(得分:-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中实现。自Perl 5.18以来,一直在讨论如何改进功能以更好地适应Perl 5,因此界面已被降级为&#34;实验&#34;状态待定更改。