¿Qué es el operador Ruby <=> (nave espacial)?

Resuelto Justin Ethier asked hace 15 años • 6 respuestas

¿ Qué es el operador Ruby <=>(nave espacial)? ¿El operador está implementado en otros idiomas?

Justin Ethier avatar May 06 '09 08:05 Justin Ethier
Aceptado

El operador de la nave espacial devolverá 1, 0o −1dependiendo del valor del argumento izquierdo en relación con el argumento derecho.

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

Se usa comúnmente para ordenar datos.

También se le conoce como operador de comparación tripartita . Perl fue probablemente el primer lenguaje en usarlo. Algunos otros lenguajes que lo admiten son Apache Groovy, PHP 7+ y C++20.

TonyArra avatar May 06 '2009 01:05 TonyArra

El método de la nave espacial es útil cuando lo defines en tu propia clase e incluyes el módulo Comparable . Luego, su clase obtiene los >, < , >=, <=, ==, and between?métodos de forma gratuita.

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>]
steenslag avatar Jan 11 '2013 16:01 steenslag

Es un operador de comparación general. Devuelve -1, 0 o +1 dependiendo de si su receptor es menor, igual o mayor que su argumento.

gnovice avatar May 06 '2009 01:05 gnovice

Te lo explicaré con un ejemplo sencillo.

  1. [1,3,2] <=> [2,2,2]

    Ruby comenzará a comparar cada elemento de ambas matrices desde el lado izquierdo. 1porque la matriz izquierda es más pequeña que 2la matriz derecha. Por lo tanto, la matriz izquierda es más pequeña que la matriz derecha. La salida será -1.

  2. [2,3,2] <=> [2,2,2]

    Como se indicó anteriormente, primero comparará el primer elemento que es igual y luego comparará el segundo elemento; en este caso, el segundo elemento de la matriz izquierda es mayor, por lo tanto, la salida es 1.

Anil Maurya avatar Jan 11 '2013 14:01 Anil Maurya

Dado que este operador reduce las comparaciones a una expresión entera, proporciona la forma más general de ordenar de forma ascendente o descendente basándose en múltiples columnas/atributos.

Por ejemplo, si tengo una serie 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.

lilole avatar Apr 11 '2017 23:04 lilole