Когда оператор космического корабля используется вне сортировки?
Это вопрос лучшей практики.
Я видел только оператор космического корабля Perl (<=>), используемый в процедурах числовой сортировки. Но это кажется полезным в других ситуациях. Я просто не могу думать о практическом использовании.
Кто-нибудь может привести пример, когда его можно использовать за пределами Perl-сортировки?
3 ответа
Я пишу систему управления для робота Джо, которая хочет пойти к роботу Мэри и перезарядить ее. Они движутся вдоль целых точек на линии. Джо начинает с $j и может пройти 1 метр в любом направлении за единицу времени. Мэри стоит на месте и не может пошевелиться - ей нужна хорошая перезарядка! Управляющая программа будет выглядеть так:
while ($m != $j) {
$j += ($m <=> $j);
}
<=>
Оператор будет полезен для алгоритма бинарного поиска. Большинство языков программирования не имеют оператора, который выполняет трехстороннее сравнение, что делает необходимым два сравнения за одну итерацию. С <=>
Вы можете сделать только один.
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;
}
В любом методе сравнения. Например, у вас может быть сложный объект, но все еще есть определенный "порядок", поэтому вы можете определить для него функцию сравнения (которую вам не нужно использовать внутри метода сортировки, хотя это было бы удобно):
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:: look_like_number.