9

我只见过数字排序例程中使用的 Perl 宇宙飞船运算符 (<=>)。但它在其他情况下似乎很有用。我只是想不出实际用途。

什么时候可以在 Perl 排序之外使用它的例子是什么?

这是一个最佳实践问题。

4

3 回答 3

7

我正在为机器人 Joe 编写一个控制系统,它想去机器人 Mary 并给她充电。它们沿着直线上的整数点移动。Joe 从 $j 开始,每个时间单位可以向任何方向走 1 米。Mary 站在 10 美元处,不能动弹——她需要好好充电!控制程序如下所示:

while ($m != $j) {
    $j += ($m <=> $j);
}
于 2009-09-02T23:09:20.133 回答
5

<=>运算符对于二分搜索算法很有用。大多数编程语言没有进行三向比较的运算符,这使得每次迭代都需要进行两次比较。有了<=>你就可以做一个。

sub binary_search {
    my $value = shift;
    my $array = shift;
    my $low   = 0;
    my $high  = $#$array;

    while ($low <= $high) {
        my $mid = $low + int(($high - $low) / 2);

        given ($array->[$mid] <=> $value) {
            when (-1) { $low  = $mid + 1 }
            when ( 1) { $high = $mid - 1 }
            when ( 0) { return $mid      }
        }
    }

    return;
}
于 2009-09-03T02:21:17.713 回答
2

在任何一种比较方法中。例如,您可能有一个复杂的对象,但它仍然具有定义的“顺序”,因此您可以为它定义一个比较函数(您不必排序方法中使用它,尽管它会很方便):

package Foo;

# ... other stuff...

# Note: this is a class function, not a method
sub cmp
{
    my $object1 = shift;
    my $object2 = shift;

    my $compare1 = sprintf("%04d%04d%04d", $object1->{field1}, $object1->{field2}, $object1->{field3});
    my $compare2 = sprintf("%04d%04d%04d", $object2->{field1}, $object2->{field2}, $object2->{field3});
    return $compare1 <=> $compare2;
}

这当然是一个完全人为的例子。但是,在我公司的源代码中,我发现几乎与上述内容完全相同,用于比较用于保存日期和时间信息的对象。

我能想到的另一种用途是用于统计分析——如果一个值反复运行在一个值列表中,您可以判断该值是高于还是低于集合的算术中位数:

use List::Util qw(sum);
# $result will be
#   -1 if value is lower than the median of @setOfValues,
#    1 if value is higher than the median of @setOfValues,
#    0 if value is equal to the median
my $result = sum(map { $value <=> $_ } @setOfValues);

这里还有一个,来自维基百科:“如果两个参数不能比较(例如其中一个是 NaN),则运算符返回 undef。”,即您可以一次确定两个数字是否是一个数字,尽管我个人认为选择不那么神秘的Scalar::Util ::looks_like_number。

于 2009-09-02T23:01:54.690 回答