我没有意识到这个看起来很简单的问题很难破解。
无论如何,我有一个包含3个浮点数的数组。我需要找出所有三个中最小的一个(在这种情况下最小的三个,我的实际代码将包含超过3个浮点数)
这是我的代码:
#!/usr/bin/perl -w
use strict;
use List::Util qw /min/;
my @array = ("2.7.4", "2.7.0", "2.7.0");
print min(@array);
输出:
Argument "2.7.4" isn't numeric in subroutine entry at min.pl line 6.
Argument "2.7.0" isn't numeric in subroutine entry at min.pl line 6.
Argument "2.7.0" isn't numeric in subroutine entry at min.pl line 6.
2.7.4
所以它输出了很多错误,输出数也错了。
我拍摄的另一个镜头是对数组进行排序(sort {$a <=> $b} @array
),然后找到最小的一个但是再次无法完成这项工作。
我可以通过数字比较进行数字编码,但如果数组中的元素数量超过三个,则代码看起来很讨厌。
你可以帮忙吗?感谢。
答案 0 :(得分:7)
这些不是浮点数,因为它们有多个小数分隔符!它们看起来像版本号。您需要Sort::Naturally或version。
答案 1 :(得分:2)
您可以使用version。
#!/usr/bin/perl
use strict;
use warnings;
use version 0.77 (); # disable importing qv
use List::Util qw'min';
my @array = map{
version->parse($_)
} qw' 2.7.4 2.7.0 2.7.0 ';
print min(@array), "\n";
或者您可以将其转换为vstring,并使用字符串比较(不推荐)。
手动
#!/usr/bin/perl
use strict;
use warnings;
sub to_vstring{
# join '', map chr, split /[.]/, shift
pack 'U*', split /[.]/, shift;
}
sub from_vstring{
# join '.', map ord, split //, shift
join '.', unpack 'U*', shift;
}
use List::Util qw'minstr'; # not min
my @array = map{
to_vstring($_)
} qw' 2.7.4 2.7.0 2.7.0 ';
print from_vstring( minstr(@array) ), "\n";
或使用字符串eval
sub to_vstring{
my $c = shift;
die "invalid vstring '$c'" unless $c =~ /^v?[0-9]+(?:[.][0-9]+)*$/;
$c = 'v'.$c unless substr($c,0,1) eq 'v';
eval $c;
}
sub from_vstring{
my $c = shift;
die "not a vstring '$c'" unless ref(\$c) eq 'VSTRING';
# join '.', map ord, split //, shift
join '.', unpack 'U*', shift;
}
如果您打算沿着这条路走,您可能需要携带原始字符串。
my @array = map{
[ to_vstring($_), $_ ]
} qw' 2.7.4 2.7.0 2.7.0 ';
my $min_pair = sort {$a->[0] cmp $b->{0]} @array;
my $min = $min_pair->[1];
print $min, "\n"
答案 2 :(得分:1)
您收到的消息不是错误,而是警告。你得到那些,因为你使用-w
开关启用它们,我建议你用行use warnings;
替换它们,因为有些模块会在你用-w
启动perl时产生意外的警告
min
无法对列表进行排序的原因是那些不是浮点数,即字符串。在比较数字上下文中的字符串时,perl会提取它认为是数字的字符串。在"2.7.4"
2.7
和"2.7.0"
的情况下,2.7
也是"12"
。
如果格式不变,字符串比较(如其他答案所示)可能有效。但是字符串比较将"9"
视为小于"2.10.1"
,因为它从左到右比较字符串的字符,并通过第一对不同的字符决定哪个字符串更大或更小。
如果您要比较的这些数字与版本号相同,则可能会出现"2.7.0"
个数字,并且字符串比较会被视为小于split
。解决这个问题的方法是将{{1}}字符串分成三个单独的数字并单独进行比较(如何将其作为练习留给读者)。