我有一个混合类型(字符串和数字)的值列表:
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
来检查您正在使用的价值类型,但我们认为可能有更好的方法弄清楚如何进行比较。提前谢谢。
答案 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;
这就是为什么smartmatch操作员被认为是错误的,需要在它停止实验之前进行更改。
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)
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;状态待定更改。