ตัวดำเนินการ Ruby <=> (ยานอวกาศ) คืออะไร


262

ตัวดำเนินการ Ruby <=>(ยานอวกาศ) คืออะไร ผู้ประกอบการใช้ภาษาอื่นหรือไม่?


1
ตอนนี้เกี่ยวกับการเปรียบเทียบอาร์เรย์? มันบอกว่าในหนังสือ "เปรียบเทียบองค์ประกอบตามองค์ประกอบส่งคืน 0 ถ้าเท่ากับ -1 ถ้าน้อยกว่า 1 ถ้ายิ่งใหญ่กว่า แต่จะเกี่ยวกับ[1,3,2] <=> [2,2,2]อะไร
เอสเอฟ

3
@SF เมื่อผู้คนเปรียบเทียบอาร์เรย์พวกเขามักจะหมายถึงการเปรียบเทียบพจนานุกรม (เช่นในพจนานุกรมคือ [1,3,2] <[2,2,2] เพราะองค์ประกอบแรกแตกต่างกัน) การเปรียบเทียบอาเรย์ (fe ใน Matlab) น้อยครั้งส่งคืนอาเรย์ของผลลัพธ์ต่อองค์ประกอบ ในกรณีนี้: [-1, 1, 0]
liori

โปรดทราบว่าอาร์เรย์ที่มีองค์ประกอบศูนย์จะเปรียบเทียบกันถ้าองค์ประกอบก่อนศูนย์ใดแตกต่างกันและไม่เทียบเคียงกันถ้าไม่มีศูนย์จะต้องเปรียบเทียบกับที่ไม่ใช่ศูนย์ เช่น [1, ไม่มี] <=> [2, 3] => -1 แต่ [1, ไม่มี]] <=> [1, 3] => ไม่มี มันแย่มาก
cliffordheath

เมื่อเปรียบเทียบอาร์เรย์เช่น[1,nil] <=> [1,3]คุณได้รับnilเนื่องจากการสอดคล้องของอัลกอริทึมเปรียบเทียบแต่ละองค์ประกอบในทางกลับกันจนผลไม่ได้<=> 0ไม่มีทางที่ Ruby จะประกาศน้อยกว่าหรือมากกว่า - ในตัวอย่างนี้เนื่องจากการเปรียบเทียบไม่สามารถทำได้ nilควรจะถือว่าเป็น "ไม่เท่ากัน" หากคุณรู้บางอย่างเกี่ยวกับข้อมูลและเช่นต้องการที่จะปฏิบัติnilตาม0Ruby ทำให้ง่ายขึ้น
lilole

คำตอบ:


359

Perl อาจเป็นภาษาแรกที่ใช้ Groovy เป็นภาษาอื่นที่รองรับ โดยทั่วไปแทนที่จะกลับ1( true) หรือ0( false) ขึ้นอยู่กับว่าข้อโต้แย้งที่มีกันหรือไม่เท่า, ผู้ประกอบการยานอวกาศที่จะกลับ1, 0หรือ−1ขึ้นอยู่กับมูลค่าของการโต้แย้งซ้ายเทียบกับอาร์กิวเมนต์ขวา

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

มันมีประโยชน์สำหรับการเรียงลำดับอาร์เรย์


27
เผง ฉันคิดว่ามันเป็นรุ่นที่หรูหรามากของ Java เปรียบเทียบได้
Mike Reedell

12
อะนาล็อกใน c # คือ IComparable.CompareTo
Sergey Mirvoda

1
ที่จริงฉันคิดว่าค่าลบหรือค่าบวกใด ๆ สามารถส่งคืนได้ 0 ยังคงหมายถึงความเท่าเทียมกัน
superluminary

1
@superluminary ซึ่งแตกต่างจากฟังก์ชั่น strcmp ของ C x ==> y ได้รับการออกแบบมาโดยเฉพาะเพื่อกลับ -1, 0, 1 หรือไม่มีถ้า x และ y ไม่เทียบเท่า (ใน Ruby และภาษาอื่น ๆ ที่ใช้ AFAIK) สิ่งนี้ทำให้ง่ายต่อการโอเวอร์โหลดผู้ปฏิบัติงานเช่นสำหรับ mixy ที่เปรียบเทียบได้ของ Ruby ใน Perl ซึ่งโอเปอเรเตอร์ส่วนใหญ่มีต้นกำเนิดมาจากส่วนใหญ่จะใช้เพื่อทำให้ไวยากรณ์ "sort BLOCK LIST" ง่ายขึ้น BLOCK เป็นรูทีนย่อยที่สามารถส่งคืนจำนวนบวกจำนวนลบหรือ 0 ขึ้นอยู่กับวิธีเรียงลำดับรายการ ผู้ประกอบการยานอวกาศมีความสะดวกในการใช้งานในบล็อก
TonyArra

2
โปรดทราบว่าหากเปรียบเทียบวัตถุทั้งสองนั้นไม่เทียบเท่าคุณจะได้รับ nil
gamov

70

วิธียานอวกาศมีประโยชน์เมื่อคุณกำหนดในชั้นเรียนของคุณเองและรวมถึงโมดูลที่เปรียบเทียบได้ ชั้นเรียนของคุณจะได้รับ>, < , >=, <=, ==, and between?วิธีการฟรี

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

มันเป็นตัวดำเนินการเปรียบเทียบทั่วไป มันจะส่งกลับทั้ง -1, 0 หรือ +1 ขึ้นอยู่กับว่าผู้รับมันน้อยกว่าเท่ากับหรือมากกว่าอาร์กิวเมนต์


18

ฉันจะอธิบายด้วยตัวอย่างง่ายๆ

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

    ทับทิมจะเริ่มเปรียบเทียบแต่ละองค์ประกอบของอาร์เรย์ทั้งสองจากด้านซ้ายมือ 1สำหรับอาร์เรย์ซ้ายมีขนาดเล็กกว่า2อาร์เรย์ขวา ดังนั้นอาร์เรย์ที่เหลือจึงมีขนาดเล็กกว่าอาเรย์ที่เหมาะสม -1ส่งออกจะ

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

    1ดังกล่าวข้างต้นมันเป็นครั้งแรกจะเปรียบเทียบองค์ประกอบแรกที่มีค่าเท่ากันแล้วมันจะเปรียบเทียบองค์ประกอบที่สองในองค์ประกอบที่สองกรณีนี้ของอาร์เรย์ซ้ายเป็นมากขึ้นด้วยเหตุนี้การส่งออกเป็น


มันเพิ่งเปรียบเทียบองค์ประกอบซ้ายแรกของแต่ละอาร์เรย์หรือเปรียบเทียบองค์ประกอบอื่น ๆ ต่อไปเช่นกัน คำอธิบายที่ดี
Kick Buttowski

1
@KickButtowski จะทำการเปรียบเทียบองค์ประกอบอื่น ๆ ต่อไปจนกว่าจะพบจำนวนที่ไม่เท่ากัน
Anil Maurya

5

เนื่องจากโอเปอเรเตอร์นี้ลดการเปรียบเทียบกับนิพจน์จำนวนเต็มจึงมีวิธีการที่ใช้โดยทั่วไปมากที่สุดในการเรียงลำดับจากน้อยไปมากหรือจากมากไปน้อยตามคอลัมน์ / แอตทริบิวต์หลายรายการ

ตัวอย่างเช่นถ้าฉันมีอาร์เรย์ของวัตถุฉันสามารถทำสิ่งนี้:

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

รูปแบบพื้นฐานนี้สามารถวางนัยทั่วไปเพื่อจัดเรียงตามจำนวนคอลัมน์ใด ๆ ในการเรียงลำดับจากน้อยไปมาก / มากไปน้อยในแต่ละ


ตัวอย่างที่ดีเพียงแค่ที่ล่าสุดไม่ทำงานตามที่คาดไว้ ปัจจัยควรเป็นพลังของสองลำดับจากมากไปน้อยเช่น 8, -4, 2, 1 วิธีที่คุณเขียน (ด้วยปัจจัย 4, -3,2,1) เช่น "อายุ + นามสกุล" มีค่ามากกว่า "zip "...
Elmar Zander

ฉันไม่คิดว่าตัวเลขเหล่านั้นหมายถึงสิ่งที่คุณคิดว่าพวกเขาหมายถึง ปัจจัยแต่ละตัวคูณ Signum ซึ่งจะเป็น -1, 0 หรือ 1 พลังของ 2 ไม่สำคัญที่นี่ -3 * (a.age <=> b.age) จะเหมือนกับ 3 * (b.age <=> a.age) เครื่องหมายของผลลัพธ์คือสิ่งที่ทำให้มันขึ้นหรือลง
lilole

ไม่มันสำคัญมาก ปัจจัยสำหรับ zip ต้องมากกว่าผลรวม (สัมบูรณ์) ของปัจจัยอื่นทั้งหมดและปัจจัยสำหรับอายุจะต้องมากกว่าจำนวนรวม (สัมบูรณ์) ของปัจจัยสุดท้ายและลำดับแรกและอื่น ๆ และลำดับที่เล็กที่สุดของตัวเลขที่เติมเต็มนั่นคือลำดับของกำลังสอง ... และ BTW ถ้าคุณอ่านความคิดเห็นของฉันอย่างระมัดระวังคุณจะเห็นว่าฉันรวมเครื่องหมายลบ ...
Elmar Zander

1
ตกลงบางทีฉันจะอธิบายเพิ่มเติมอีกเล็กน้อยว่า: ด้วยปัจจัย (4, -3,2,1) และผลลัพธ์จากยานอวกาศ op (1,1, -1, -1) ผลรวมถ่วงน้ำหนักคือ -2 แต่ มันจะต้องเป็นบวก! มิฉะนั้นซิปที่ใหญ่กว่าจะมาก่อนไฟล์ซิปที่เล็กกว่า สิ่งนี้จะไม่เกิดขึ้นกับปัจจัย (8, -4,2,1)
Elmar Zander

1
ฉันเห็นแล้วตอนนี้ถ้าเรียงลำดับในคอลัมน์> 2 จำเป็นต้องใช้กำลังของ 2 ขอขอบคุณที่ช่วยแก้ไขนี้ ขออภัยโลกถ้าการเรียงลำดับคอลัมน์ของคุณ 3 คอลัมน์ขึ้นไปผิดพลาด
ม่วง

-2

<=> ผู้ประกอบการ 'ยานอวกาศ' คืออะไร

ให้เป็นไปตาม RFC ที่แนะนำผู้ประกอบการ , $ 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

ตัวอย่าง:

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

มากกว่า:

// 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.