¿Qué es el <=>
operador Ruby (nave espacial)? ¿El operador está implementado por otros idiomas?
fuente
¿Qué es el <=>
operador Ruby (nave espacial)? ¿El operador está implementado por otros idiomas?
Perl fue probablemente el primer idioma en usarlo. Groovy es otro idioma que lo admite. Básicamente en lugar de regresar 1
( true
) o 0
( false
) dependiendo de si los argumentos son iguales o desiguales, el operador de la nave espacial regresará 1
, 0
o −1
dependiendo del valor del argumento de la izquierda en relación con el argumento de la derecha.
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
Es útil para ordenar una matriz.
El método de nave espacial es útil cuando lo define en su propia clase e incluye el módulo Comparable . Tu clase obtiene los >, < , >=, <=, ==, and between?
métodos gratis.
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>]
Es un operador de comparación general. Devuelve un -1, 0 o +1 dependiendo de si su receptor es menor, igual o mayor que su argumento.
Explicaré con un simple ejemplo
[1,3,2] <=> [2,2,2]
Ruby comenzará a comparar cada elemento de ambos conjuntos desde el lado izquierdo.
1
para la matriz izquierda es más pequeña que 2
la matriz derecha. Por lo tanto, la matriz izquierda es más pequeña que la matriz derecha. La salida será -1
.
[2,3,2] <=> [2,2,2]
Como arriba, primero comparará el primer elemento que es igual, luego comparará el segundo elemento, en este caso, el segundo elemento de la matriz izquierda es mayor, por lo tanto, la salida es 1
.
Dado que este operador reduce las comparaciones a una expresión entera, proporciona la forma de propósito más general para ordenar ascendente o descendente en función de múltiples columnas / atributos.
Por ejemplo, si tengo una variedad de objetos, puedo hacer cosas como esta:
# `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
Este patrón básico se puede generalizar para ordenar por cualquier número de columnas, en cualquier permutación de ascendente / descendente en cada una.
Qué es
<=>
(El operador de la 'nave espacial')
<=>
$ 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
Ejemplo:
//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
MÁS:
// 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]
?[1,nil] <=> [1,3]
que obtiene,nil
debido a la coherencia del algoritmo, compare cada elemento por turnos hasta que el<=>
resultado NO sea0
. No hay forma de que Ruby declare menor o mayor que en este ejemplo, ya que simplemente no se puede hacer una comparación. Elnil
debe ser tratado como "no igual". Si usted sabe algo acerca de los datos, por ejemplo, y quiere tratarnil
como0
, Ruby hace tan fácil.