Ruby <=> (uzay gemisi) operatörü nedir?


262

Ruby <=>(uzay gemisi) operatörü nedir? Operatör başka diller tarafından uygulanıyor mu?


1
Şimdi dizileri karşılaştırmaya ne dersiniz? Kitapta "öğeyi öğeye göre karşılaştırır, eşitse 0, daha küçükse -1, daha büyükse 1 döndürür, ama ne olacak [1,3,2] <=> [2,2,2]?
SF.

3
@SF, insanlar dizileri karşılaştırdıklarında, genellikle sözlükbilimsel olarak karşılaştırmak isterler (sözlükte olduğu gibi, yani [1,3,2] <[2,2,2], çünkü ilk elemanlar farklıdır). Nadiren (Matlab'da fe) dizi karşılaştırması, öğe başına bir sonuç dizisi döndürür; bu durumda: [-1, 1, 0].
liori

Nil elemanları içeren diziler, herhangi bir sıfırdan önceki elemanlar farklıysa karşılaştırılabilir, bir sıfırın sıfır olmayanlarla karşılaştırılması gerektiğinde karşılaştırılamaz. Yani [1, nil] <=> [2, 3] => -1, ancak [1, nil] <=> [1, 3] => nil. Bu temelde berbat.
cliffordheath

[1,nil] <=> [1,3]Sizin gibi dizileri karşılaştırırken nilalgoritmanın tutarlılığı nedeniyle <=>sonuç elde edilinceye kadar her bir öğeyi sırayla karşılaştırın 0. Ruby'nin bu örnekten daha az veya daha fazla beyan etmesinin bir yolu yoktur, çünkü karşılaştırma yapılamaz. nil"Eşit değil" olarak ele alınmalıdır. Verilerle ilgili bir şeyler bilmek ve örneğin tedavi istiyorsanız nilolarak 0, Yakut kolay ortaya koyuyor.
lilole

Yanıtlar:


359

Perl muhtemelen onu kullanan ilk dildi. Groovy, onu destekleyen başka bir dildir. Temel olarak döndürmek yerine 1( true) ya da 0( false) bağımsız değişkenler, eşit veya eşit olmayan olup olmamasına bağlı olarak, uzay operatör döner 1, 0ya da −1doğru değişken için sol bağımsız değişken nisbetle değerine bağlı olarak.

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

Bir diziyi sıralamak için kullanışlıdır.


27
Kesinlikle. Ben Java'nın Karşılaştırılabilir çok zarif bir sürümü olarak düşünüyorum.
Mike Reedell

12
c # analog IComparable.CompareTo olduğunu
Sergey Mirvoda

1
Aslında herhangi bir olumsuz ya da pozitif değer iade edilebilir düşünüyorum. 0 hala eşitlik demektir.
superluminary

1
@superluminary C'nin strcmp işlevinin aksine, x <=> y ​​özellikle x ve y karşılaştırılamazsa (Ruby ve AFAIK kullanan diğer dillerde) yalnızca -1, 0, 1 veya nil döndürecek şekilde tasarlanmıştır. Bu, Ruby's Comparable mixin gibi operatörün aşırı yüklenmesini kolaylaştırır. Operatörün büyük olasılıkla kaynaklandığı Perl'de, temel olarak "sıralama BLOK LİSTESİ" sözdizimini basitleştirmek için kullanıldı. BLOK, liste öğelerinin nasıl sıralanması gerektiğine bağlı olarak herhangi bir pozitif sayı, negatif sayı veya 0 döndürebilen bir alt yordamdır. Uzay gemisi operatörü blokta kullanmak için uygundur.
TonyArra

2
Karşılaştırılan iki nesne karşılaştırılabilir değilse, bir nil
gamov

70

Uzay gemisi yöntemi, kendi sınıfınızda tanımladığınızda ve Karşılaştırılabilir modülünü eklediğinizde kullanışlıdır . Daha sonra sınıfınız >, < , >=, <=, ==, and between?yöntemleri ücretsiz olarak alır .

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

Genel bir karşılaştırma operatörüdür. Alıcının bağımsız değişkeninden küçük, eşit veya büyük olmasına bağlı olarak -1, 0 veya +1 döndürür.


18

Basit bir örnekle açıklayacağım

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

    Ruby, her iki dizinin her bir öğesini sol taraftan karşılaştırmaya başlayacaktır. 1sol dizi için sağ dizi küçüktür 2. Dolayısıyla sol dizi sağ diziden daha küçüktür. Çıktı olacak -1.

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

    Yukarıda olduğu gibi ilk olarak eşit olan ilk elemanı karşılaştırır, sonra ikinci elemanı karşılaştırır, bu durumda sol dizinin ikinci elemanı daha büyük olur, dolayısıyla çıktı olur 1.


her dizinin ilk sol öğesini mi karşılaştırıyor yoksa diğer öğeleri de karşılaştırmaya devam ediyor mu? iyi açıklama
Kick Buttowski

1
@KickButtowski eşit olmayan bir sayı bulamadıkça diğer öğeleri karşılaştırmaya devam eder.
Anil Maurya

5

Bu işleç, bir tamsayı ifadesiyle karşılaştırmaları azalttığından, birden çok sütuna / özniteliğe göre artan veya azalan sıralamanın en genel amaçlı yolunu sağlar.

Örneğin, nesnelerin bir dizi varsa ben böyle şeyler yapabilirsiniz:

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

Bu temel desen, her birine artan / azalan herhangi bir permütasyonda, herhangi bir sayıda sütuna göre sıralamak üzere genelleştirilebilir.


Güzel örnekler, sadece sonuncusu beklendiği gibi çalışmıyor. Faktörler, azalan sırada ikisinin gücü olmalıdır, yani 8, -4, 2, 1. Yazma şekliniz (faktörler 4, -3,2,1 ile), örneğin "yaş + soyadı", "zip" ten daha fazla sayılır "...
Elmar Zander

Bu sayıların ne demek istediğini düşündüğünü sanmıyorum. Her bir faktör, -1, 0 veya 1 olacak olan işareti çarpar. Burada 2'nin gücü önemli değildir. -3 * (a.age <=> b.age) 3 * (b.age <=> a.age) ile tamamen aynıdır. Sonucun işareti, artan veya azalan şeydir.
lilole

Hayır, çok önemli. Zip faktörü, diğer tüm faktörlerin (mutlak) toplamından daha büyük olmalı ve yaş faktörü, son ve ilk faktörlerin (mutlak) toplamından daha büyük olmalıdır. Ve yerine getiren en küçük sayı dizisi, iki güç dizisidir ... Ve BTW yorumumu dikkatlice okursanız, eksi işaretini dahil ettiğimi görürdünüz ...
Elmar Zander

1
Tamam, belki biraz daha ayrıntıya gireceğim: faktörler (4, -3,2,1) ve uzay gemisi op (1,1, -1, -1) 'nin sonuçları ile ağırlıklı toplam -2'dir, ancak olumlu olması gerekiyor! Aksi takdirde, büyük fermuar küçük fermuardan önce gelir. Bu faktörlerle olmaz (8, -4,2,1).
Elmar Zander

1
Ah şimdi görüyorum, eğer> 2 sütuna göre sıralama yapıyorsanız, 2'nin gücü gereklidir. Bunu düzeltmeye yardımcı olduğunuz için teşekkürler. 3 veya daha fazla sütun sıralamanız yanlışsa, üzgünüm dünya.
lilole

-2

Nedir <=> ('Uzay Gemisi' Operatörü)

Operatörü tanıtan RFC'ye göre , $ 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

Misal:

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

DAHA:

// 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.