什么是 Ruby 的 <=>(太空船)运算符?其他编程语言是否实现了这个运算符?
什么是 Ruby 的 <=>(太空船)运算符?其他编程语言是否实现了这个运算符?
太空船操作符将根据左边参数与右边参数的大小关系返回1
、0
或−1
。
a <=> b :=
if a < b then return -1
if a = b then return 0
if a > b then return 1
if a and b are not comparable then return nil
它通常用于数据排序。
它也被称为“三路比较运算符”。Perl 可能是第一个使用它的语言。还有其他支持它的语言,如 Apache Groovy、PHP 7+ 和 C++20。
当您在自己的类中定义并包含Comparable模块时,宇宙飞船方法很有用。然后您的类将免费获得>, < , >=, <=, ==和between?
等方法。
class Card
include Comparable
attr_reader :value
def initialize(value)
@value = value
end
def <=> (other) #1 if self>other; 0 if self==other; -1 if self<other
self.value <=> other.value
end
end
a = Card.new(7)
b = Card.new(10)
c = Card.new(8)
puts a > b # false
puts c.between?(a,b) # true
# Array#sort uses <=> :
p [a,b,c].sort # [#<Card:0x0000000242d298 @value=7>, #<Card:0x0000000242d248 @value=8>, #<Card:0x0000000242d270 @value=10>]
这是一个通用的比较运算符。它根据其接收方是否小于、等于或大于其参数返回-1、0或+1。
我将以简单的例子来解释
[1,3,2] <=> [2,2,2]
Ruby将从左侧开始比较两个数组的每个元素。
左侧数组的1
小于右侧数组的2
。因此,左侧数组小于右侧数组。输出为-1
。
[2,3,2] <=> [2,2,2]
与上面相似,它将首先比较相等的第一个元素,然后将比较第二个元素,在这种情况下,左侧数组的第二个元素大,因此输出为1
。
由于此运算符将比较转换为整数表达式,因此它提供了最通用的方法来基于多个列/属性升序或降序排序。
例如,如果我有一个对象数组,则可以执行以下操作:
# `sort!` modifies array in place, avoids duplicating if it's large...
# Sort by zip code, ascending
my_objects.sort! { |a, b| a.zip <=> b.zip }
# Sort by zip code, descending
my_objects.sort! { |a, b| b.zip <=> a.zip }
# ...same as...
my_objects.sort! { |a, b| -1 * (a.zip <=> b.zip) }
# Sort by last name, then first
my_objects.sort! { |a, b| 2 * (a.last <=> b.last) + (a.first <=> b.first) }
# Sort by zip, then age descending, then last name, then first
# [Notice powers of 2 make it work for > 2 columns.]
my_objects.sort! do |a, b|
8 * (a.zip <=> b.zip) +
-4 * (a.age <=> b.age) +
2 * (a.last <=> b.last) +
(a.first <=> b.first)
end
<=>
是什么(“太空船”运算符)
<=>
$b - 0 if $a == $b
- -1 if $a < $b
- 1 if $a > $b
- Return 0 if values on either side are equal
- Return 1 if value on the left is greater
- Return -1 if the value on the right is greater
例子:
//Comparing Integers
echo 1 <=> 1; //ouputs 0
echo 3 <=> 4; //outputs -1
echo 4 <=> 3; //outputs 1
//String Comparison
echo "x" <=> "x"; // 0
echo "x" <=> "y"; //-1
echo "y" <=> "x"; //1
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
// Objects
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 0
[1,3,2] <=> [2,2,2]
怎么处理? - SF.[1,nil] <=> [1,3]
这样的数组时,由于算法的一致性,你会得到一个nil
,它会逐个比较每个元素,直到<=>
的结果不是0
。在这个例子中,Ruby 没有办法声明小于或大于,因为根本无法进行比较。应该将nil
视为“不相等”。如果您了解数据的某些信息,并且想将nil
视为0
,那么 Ruby 可以轻松实现。 - lilole