What is the Ruby <=> (spaceship) operator?

后端 未结 6 1794
夕颜
夕颜 2020-11-22 14:42

What is the Ruby <=> (spaceship) operator? Is the operator implemented by any other languages?

相关标签:
6条回答
  • 2020-11-22 15:18

    Since this operator reduces comparisons to an integer expression, it provides the most general purpose way to sort ascending or descending based on multiple columns/attributes.

    For example, if I have an array of objects I can do things like this:

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

    This basic pattern can be generalized to sort by any number of columns, in any permutation of ascending/descending on each.

    0 讨论(0)
  • 2020-11-22 15:30

    Perl was likely the first language to use it. Groovy is another language that supports it. Basically instead of returning 1 (true) or 0 (false) depending on whether the arguments are equal or unequal, the spaceship operator will return 1, 0, or −1 depending on the value of the left argument relative to the right argument.

    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
    

    It's useful for sorting an array.

    0 讨论(0)
  • 2020-11-22 15:30

    I will explain with simple example

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

      Ruby will start comparing each element of both array from left hand side. 1 for left array is smaller than 2 of right array. Hence left array is smaller than right array. Output will be -1.

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

      As above it will first compare first element which are equal then it will compare second element, in this case second element of left array is greater hence output is 1.

    0 讨论(0)
  • 2020-11-22 15:32

    What is <=> ( The 'Spaceship' Operator )

    According to the RFC that introduced the 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
    

    Example:

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

    MORE:

    // 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
    
    0 讨论(0)
  • 2020-11-22 15:36

    It's a general comparison operator. It returns either a -1, 0, or +1 depending on whether its receiver is less than, equal to, or greater than its argument.

    0 讨论(0)
  • 2020-11-22 15:38

    The spaceship method is useful when you define it in your own class and include the Comparable module. Your class then gets the >, < , >=, <=, ==, and between? methods for free.

    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>]
    
    0 讨论(0)
提交回复
热议问题