web-dev-qa-db-fra.com

Qu'est-ce que l'opérateur Ruby <=> (vaisseau spatial))?

Quel est le Ruby <=> _ opérateur (vaisseau spatial)? L'opérateur est-il implémenté par d'autres langues?

243
Justin Ethier

Perl était probablement la première langue à l'utiliser. Groovy est un autre langage qui le prend en charge. Fondamentalement, au lieu de retourner 1 (true) ou 0 (false) selon que les arguments sont égaux ou non, l’opérateur de vaisseau spatial retournera 1, 0, ou −1 en fonction de la valeur de l'argument de gauche par rapport à l'argument de droite.

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

C'est utile pour trier un tableau.

324
TonyArra

La méthode du vaisseau spatial est utile lorsque vous la définissez dans votre propre classe et incluez le module comparable . Votre classe obtient alors le >, < , >=, <=, ==, and between? méthodes gratuitement.

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>]
67
steenslag

C'est un opérateur de comparaison général. Il renvoie -1, 0 ou +1 selon que son récepteur est inférieur, égal ou supérieur à son argument.

19
gnovice

Je vais expliquer avec un exemple simple

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

    Ruby commencera à comparer chaque élément des deux tableaux du côté gauche. 1 pour le tableau de gauche est inférieur à 2 du tableau de droite. Par conséquent, le tableau de gauche est plus petit que le tableau de droite. La sortie sera -1.

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

    Comme ci-dessus, il comparera d'abord le premier élément égal, puis le deuxième élément; dans ce cas, le deuxième élément du tableau de gauche est supérieur et donc la sortie est 1.

15
Anil Maurya

Etant donné que cet opérateur réduit les comparaisons à une expression entière, il constitue le moyen le plus général de trier par ordre croissant ou décroissant en fonction de plusieurs colonnes/attributs.

Par exemple, si j'ai un tableau d'objets, je peux faire les choses suivantes:

# `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
my_objects.sort! do |a, b|
      4 * (a.Zip   <=> b.Zip) +
     -3 * (a.age   <=> b.age) +
      2 * (a.last  <=> b.last) +
          (a.first <=> b.first)
end

Ce modèle de base peut être généralisé pour trier par un nombre quelconque de colonnes, dans toute permutation ascendante/descendante sur chacune.

3
lilole