Apakah yang dimaksud dengan operator Ruby <=> (pesawat ruang angkasa)?


262

Apa itu <=>operator Ruby (pesawat ruang angkasa)? Apakah operator diimplementasikan oleh bahasa lain?


1
Sekarang bagaimana dengan membandingkan array? Dikatakan dalam buku "membandingkan elemen demi elemen, mengembalikan 0 jika sama, -1 jika lebih rendah, 1 jika lebih besar, tetapi bagaimana [1,3,2] <=> [2,2,2]?
SF.

3
@ SF, ketika orang membandingkan array, mereka biasanya bermaksud membandingkan leksikografis (seperti dalam kamus, yaitu [1,3,2] <[2,2,2] karena elemen pertama berbeda). Perbandingan array yang jarang (fe in Matlab) mengembalikan array hasil per elemen; dalam hal ini: [-1, 1, 0].
liori

Perhatikan bahwa Array yang berisi elemen nil sebanding jika elemen sebelum nil berbeda, dan tidak sebanding jika nil harus dibandingkan dengan non-nil. Yaitu [1, nil] <=> [2, 3] => -1, tetapi [1, nil] <=> [1, 3] => nihil. Ini menyebalkan, pada dasarnya.
cliffordheath

Saat membandingkan array seperti yang [1,nil] <=> [1,3]Anda dapatkan nilkarena konsistensi algoritme, membandingkan setiap elemen pada gilirannya hingga <=>hasilnya TIDAK 0. Tidak ada cara bagi Ruby untuk menyatakan kurang dari atau lebih besar dari dalam contoh ini, karena perbandingan tidak dapat dibuat. The nilharus diperlakukan sebagai "tidak sama". Jika Anda mengetahui sesuatu tentang data, dan mis. Ingin diperlakukan nilsebagai 0, Ruby membuatnya mudah.
lilole

Jawaban:


359

Perl kemungkinan merupakan bahasa pertama yang menggunakannya. Groovy adalah bahasa lain yang mendukungnya. Pada dasarnya bukannya kembali 1( true) atau 0( false) tergantung pada apakah argumen yang sama atau tidak sama, operator pesawat ruang angkasa akan kembali 1, 0atau −1tergantung pada nilai argumen kiri relatif terhadap argumen yang tepat.

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

Ini berguna untuk mengurutkan array.


27
Persis. Saya menganggapnya sebagai versi Java's Comparable yang sangat elegan.
Mike Reedell

12
analog dalam c # adalah IComparable.CompareTo
Sergey Mirvoda

1
Sebenarnya saya pikir nilai negatif atau positif dapat dikembalikan. 0 masih berarti kesetaraan.
superluminary

1
@superluminary Tidak seperti fungsi strcmp C, x <=> y ​​dirancang khusus untuk hanya mengembalikan -1, 0, 1, atau nihil jika x dan y tidak sebanding (dalam Ruby dan bahasa lain yang menggunakannya AFAIK). Ini membuatnya mudah untuk membebani operator, seperti untuk mixin Sebanding Ruby. Di Perl, tempat operator kemungkinan besar berasal, itu digunakan terutama untuk menyederhanakan sintaks "sort BLOCK LIST". BLOCK adalah subrutin yang dapat mengembalikan angka positif, angka negatif, atau 0 tergantung pada bagaimana item daftar harus diurutkan. Operator pesawat ruang angkasa nyaman untuk digunakan di blok.
TonyArra

2
Perhatikan bahwa jika dua objek yang dibandingkan tidak sebanding, Anda akan mendapatkan nih
gamov

70

Metode pesawat ruang angkasa berguna ketika Anda mendefinisikannya di kelas Anda sendiri dan termasuk modul Sebanding . Kelas Anda kemudian mendapatkan >, < , >=, <=, ==, and between?metode secara 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>]

20

Ini adalah operator perbandingan umum. Mengembalikan nilai -1, 0, atau +1 tergantung pada apakah receivernya kurang dari, sama dengan, atau lebih besar dari argumennya.


18

Saya akan jelaskan dengan contoh sederhana

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

    Ruby akan mulai membandingkan setiap elemen dari kedua array dari sisi kiri. 1untuk array kiri lebih kecil 2dari array kanan. Oleh karena itu array kiri lebih kecil dari array kanan. Output akan menjadi -1.

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

    Seperti di atas pertama akan membandingkan elemen pertama yang sama maka akan membandingkan elemen kedua, dalam hal ini elemen kedua array kiri lebih besar maka outputnya adalah 1.


apakah itu hanya membandingkan elemen kiri pertama dari setiap array atau terus membandingkan elemen lain juga? penjelasan yang bagus
Jurus Buttowski

1
@KickButtowski terus membandingkan elemen lain kecuali ia menemukan angka yang tidak sama.
Anil Maurya

5

Karena operator ini mengurangi perbandingan ke ekspresi integer, ia menyediakan cara tujuan paling umum untuk mengurutkan naik atau turun berdasarkan beberapa kolom / atribut.

Misalnya, jika saya memiliki array objek, saya dapat melakukan hal-hal seperti ini:

# `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

Pola dasar ini dapat digeneralisasi untuk mengurutkan berdasarkan sejumlah kolom, dalam permutasi naik / turun pada masing-masing kolom.


Contoh yang bagus, hanya saja yang terakhir tidak berfungsi seperti yang diharapkan. Faktor-faktor haruslah kekuatan dua dalam urutan menurun, yaitu 8, -4, 2, 1. Cara Anda menulisnya (dengan faktor 4, -3,2,1), misalnya "usia + nama belakang" lebih dari "zip" "...
Elmar Zander

Saya tidak berpikir angka-angka itu berarti apa yang Anda pikirkan artinya. Setiap faktor mengalikan signum, yang akan menjadi -1, 0, atau 1. Kekuatan 2 tidak masalah di sini. -3 * (a.age <=> b.age) persis sama dengan 3 * (b.age <=> a.age). Tanda hasilnya adalah apa yang membuatnya naik atau turun.
lilole

Tidak, itu sangat penting. Faktor untuk zip harus lebih besar dari jumlah (absolut) dari semua faktor lain, dan faktor usia harus lebih besar dari jumlah (absolut) faktor terakhir dan pertama, dan seterusnya. Dan urutan angka terkecil yang memenuhi itu adalah urutan kekuatan dua ... Dan BTW jika Anda membaca komentar saya dengan cermat, Anda akan melihat bahwa saya menyertakan tanda minus ...
Elmar Zander

1
Ok, mungkin saya akan menguraikan sedikit lebih banyak tentang itu: dengan faktor (4, -3,2,1) dan hasil dari operasi ruang angkasa (1,1, -1, -1) jumlah tertimbang adalah -2, tetapi itu harus positif! Kalau tidak, zip yang lebih besar akan datang sebelum zip yang lebih kecil. Ini tidak akan terjadi dengan faktor (8, -4,2,1).
Elmar Zander

1
Ah saya mengerti sekarang, jika mengurutkan pada> 2 kolom maka kekuatan 2 diperlukan. Terima kasih telah membantu memperbaiki ini. Maaf dunia jika 3 atau lebih kolom Anda menyortir ternyata salah.
lilole

-2

Apa itu <=> (Operator 'Pesawat Luar Angkasa')

Menurut RFC yang memperkenalkan operator , $ a <=>$ 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

Contoh:

//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

LEBIH:

// 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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.