Operator <=> in Ruby [duplicate] - ruby

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the Ruby <=> (spaceship) operator?
I saw a code and an operator I'm unfamiliar with
#array << {:suffix=> substring, :index => i}
#array.sort! { |x,y| x[:suffix] <=> y[:suffix]}
I can't do google on it. What does <=> do?

This is the spaceship operator, it was borrowed from Perl. It is commonly used for sorting, because it returns -1 if left operand is less than right operand, 1 if right operand is greater than the left and returns 0 otherwise.
1 <=> 2 # => -1
2 <=> 1 # => 1
1 <=> 1 # => 0

It does comparison defined for the particular class. If it is the case that ... < ... is true, it returns -1, if ... == ... is true, then 0, and if ... > ... is true, then 1.

It's called the spaceship operator.
For the core numeric and string classes, it's a comparison operator that returns -1, 0, or 1.
In theory, a class can define any operator to do anything it wants, but this will be the method that is used when sorting. It may make sense to define <=> for an arbitrary application class if that class will ever need to be ordered.

Related

What's the proper way to use the <=> operator in Ruby? [duplicate]

This question already has answers here:
What is the Ruby <=> (spaceship) operator?
(6 answers)
Closed 4 years ago.
I don't quite understand how this works. I guess a large part of it is because I'm used to C and its low-level data structures, and programming at a higher level of abstraction takes some getting used to. Anyway, I was reading The Ruby Programming Language, and I came to the section about ranges and how you can use the <=> operator as sort of a shorthand for what in C you would have to implement as a sequence of if-else statements. It returns either -1, 0, or 1 depending on the results of the comparison. I decided to try it out with the following statement:
range = 1..100
r = (100 <=> range)
print( r )
The result is an empty string. So my question is, how does this operator work; what data type does it return (I assume the return value is an integer type but I can't say for sure); and finally what is the proper way to use it? Thanks for your time, and sorry if this was already answered (I didn't see it in the listing).
The <=> operator is meant to compare two values that can be compared directly, as in strings to strings or numbers to numbers. It can't magically compare two different things, Ruby doesn't convert for you like that.
As such you need to use it in the right context:
1 <=> 2
# => -1
2 <=> 1
# => 1
1 <=> 1
# => 0
When the two things can't be compared you get nil. Note that this is different from "empty string":
1 <=> '1'
# => nil
That means "invalid comparison". The <=> operator is being nice here because in other situations you get an exception:
1 < '1'
# => ArgumentError: comparison of Integer with String failed
You can also use this operator to make your own Comparable compatible class:
class Ordered
include Comparable
attr_reader :sequence
def initialize(sequence)
#sequence = sequence
end
def <=>(other)
self.sequence <=> other.sequence
end
end
Then you can do this:
a = Ordered.new(10)
b = Ordered.new(2)
[ a, b ].sort
# => [#<Ordered:0x00007ff1c6822b60 #sequence=2>, #<Ordered:0x00007ff1c6822b88 #sequence=10>]
Where those come out in order. The <=> implementation handles how these are sorted, and you can finesse that depending on how complex your sorting rules are.
Using the return values -1, 0, and 1 only as labels describing different states, you can write a condition that depends on the order between two numbers:
case a <=> b
when -1 then # a is smaller than b. Do something accordingly
when 0 then # a equals b. Do something accordingly
when 1 then # a is larger than b. Do something accordingly
end
Or, a use case where you can make use of the values -1, 0, and 1, is when you want to get the (non-negative) difference between two numbers a and b without using the abs method. The following:
(a - b) * (a <=> b)
will give the difference.
Add to the other answers this snippet: The "spaceship operator" returns -1, 0, or 1 so you can use it when comparing items in a .sort call:
events.sort {|x, y| y.event_datetime <=> x.event_datetime}
0 means the two items are the same, 1 means they are different but in the correct sort order, and -1 means they are out of order. The above example reverses x and y to sort into descending order.
In C, the function strcmp() has roughly the same behavior, to fit with qsort(), with the same semantics.

what makes an operator <=> in the block min? [duplicate]

This question already has answers here:
What is the Ruby <=> (spaceship) operator?
(6 answers)
Closed 6 years ago.
Have following example of code:
%w{ Ruby C APL Perl Smalltalk}.min {|a,b| a.size <=> b.size}
return "C"
Can you explain me why "C"? What makes an operator "<=>" ?
The Spaceship operator returns -1 if the left is less than the right, 0 if they are equal, and 1 if the left is greater than the right.
In this case, you're comparing the length of each word in the array and returning the shortest word. If you removed .size from the variable in the block, it would instead return the first word that occurs alphabetically (i.e. 'APL').
What is the Ruby <=> (spaceship) operator?

Why do we need spaceship operator? [duplicate]

This question already has answers here:
What is the Ruby <=> (spaceship) operator?
(6 answers)
Closed 7 years ago.
If we have <, >, and ==, the total order is determined by those. Why do we need <=>?
we Don't need <=>.
a<=>b
is equivalent to:
if a<b
return -1
elsif a>b
return 1
else
return 0
end
It is there for convenience and it was taken from perl.
<=> is the basis of Comparable, so you don't have to implement all of the compare functions yourself. It's easier and less error-prone to just implement one function instead of three.
The "spaceship" operator is for comparison, not equality. It's similar in concept to C's strcmp function.
From the String class:
string <=> other_string → -1, 0, +1 or nil
Comparison — Returns -1, 0, +1 or nil depending on whether string is less than, equal to, or greater than other_string.
In short, == returns a boolean expressing equality, while <=> returns a number expressing comparative value. If the first object is of greater value than the second, <=> returns +1. If it's of lesser value, -1 is returned. If the two have the same value, 0 is returned.
The "value" of an object can be defined to be just about anything. For String, however, <=> checks the lexicographic ordering of the two arguments.
Therefore:
"abc" == "abc" # true
("abc" <=> "abc") == 0 # true
You are correct that there is redundancy between <, ==, > and <=>. In fact, when <, ==, > are defined, <=> is automatically defined.
This operator is sometimes called a "signum" function. It provides the most concise way to customize sort order. For example:
require "ostruct"
# Fake "rows" with OpenStructs
my_data = [
OpenStruct.new({ :name => "Ben", :age => 50 }),
OpenStruct.new({ :name => "Abe", :age => 50 }),
OpenStruct.new({ :name => "Cab", :age => 51 })
]
# Sort by age descending, then name ascending
puts my_data.sort { |a, b| 2 * (b.age <=> a.age) + (a.name <=> b.name) }
This works because the value from <=> is always -1, 0, or 1. I don't know of a more efficient way to do general-purpose sorting.

What is the difference between '&&' and '&' in Ruby

Recently, I observed a very interesting result in Ruby while making use of && and & for the input combination of 0 & 1.
Can someone please explain the below output with respect to the above mentioned two operators? The below is implemented using Ruby 2.0.0-p451
2.0.0-p451 :006 > 0 && 1
=> 1
2.0.0-p451 :008 > 0 & 1
=> 0
Thank you
&& is the logical AND operator. It will be truthy, IFF both operands are truthy. And it is lazy (aka short-circuiting), which means it will stop evaluating as soon as the result has been fully determined. (So, since both operands need to be truthy, if the first operand is falsy, you already know that the result is going to be falsy, without even evaluating the second operand.) It will also not just return true or false, but rather return the operand which determines the outcome. IOW: if a is falsy, it'll return a, otherwise it'll return b:
nil && (loop {})
# => nil
# Note: the infinite loop is *not* evaluated
# Note: the return value is nil, not false
true && nil
# => nil
true && 'Hello'
# => 'Hello'
& simply calls the method &. It will do whatever the object wants it to do:
def (weirdo = Object.new).&(other)
puts 'Whoah, weird!'
'Hello, ' + other
end
weirdo & 'World'
# Whoah, weird!
# => 'Hello, World'
In general, & and its brother | are expected to perform conjunction and disjunction. So, for booleans, they are perform AND and OR (TrueClass#&, FalseClass#&, NilClass#&, TrueClass#|, FalseClass#|, NilClass#|) with the exception that & and | are standard method calls and thus always evaluate their argument and that they always return true or false and not their arguments.
For Sets, they perform set intersection and set union: Set#&, Set#|. For other collections (specifically Arrays), they also perform set operations: Array#&, Array#|.
For Integers, they perform BITWISE-AND of the two-complement's binary representation: Fixnum#&, Bignum#&, Fixnum#|, Bignum#|.
&& is a boolean and. It returns the second argument if the first argument is true-ish. Because 0 is true-ish in Ruby, 1 is returned.
& is a bitwise and. It compares the bit representation of the values. Because (imaging 8 bit) 00000000 (0) and 00000001 (1) have no 1 digits in common, 00000000 (0) is returned.
This page gives a good explanation of the different operators in Ruby.
&& is logical AND operator in ruby.
> a = true
> b = true
> c = false
> a && b
=> true
> a && c
=> false
& is the bitwise AND operator in ruby. Per the wikipedia article on the description for the "bitwise AND operator":
A bitwise AND takes two binary representations of equal length and
performs the logical AND operation on each pair of corresponding bits.
The result in each position is 1 if the first bit is 1 and the second
bit is 1; otherwise, the result is 0.
One is a boolean operator, the other is a bitwise operator:
# Bitwise operators
a = 78 # 01001110
b = 54 # 00110110
puts (a&b) # 00000110 = 6
puts (a|b) # 01111110 = 126
puts (a^b) # 01111000 = 120
puts (~a) # 10110001 = -79
puts (a<<2) # 00111000 = 312
puts (a>>2) # 00010011 = 19
http://www.public.traineronrails.com/courses/ruby/pages/008-rubyoperators.html
&& is logical and. Which is to say, a && b returns true if a is true and b is true. & is bitwise and. In (almost) any other language, logical and of 0 and 1 would be 0, because (almost) all other languages consider 0 to be false. But in ruby, anything except nil and false are considered to be truthy.
&& is a Logical operator which will always return a boolean value.
z It's either true if both of the values are true
true && true
and will return false if any of the value is false
false && true
Now comes to second point & Operator.
Here are two answer for the & Operator.
& is a Bitwise operator as mentioned in above answers, It compares bit representation in the form of 0 and 1.
Another Important answer is, In upgradation of Ruby 2.6 its implementation is somewhat modified.
& is represented as intersection operator
For ex:
[1, 2, 3] & [2, 3, 4]
$ [2, 3]

Ruby Equal to vs Comparison;

I need help for understanding - What is the difference between Equal to and Comparison?
Here is the case
x == y means `Equal to`
x = 10 and y = 10
puts "X and Y are equal" if x == y
puts "X and Y are equal" if x <=> y
I know when and where can I use equal to, but when and where can I use Comparison <=>
Thanks
When you want to compare? It returns -1, 0, 1. For example, sorting users by first name:
users_by_first = users.sort { |u1, u2| u1.fname <=> u2.fname }
Here's another SO question asking about the spaceship operator.
<=> General comparison operator. Returns -1, 0, or +1, depending on whether its receiver is less than, equal to, or greater than its argument.
http://ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html
This is useful for sorting, for one thing.
Equality operators: == and !=
The == operator, also known as equality or double equal, will return true if both objects are equal and false if they are not.
"koan" == "koan" # Output: => true
The != operator, AKA inequality or bang-tilde, is the opposite of ==. It will return true if both objects are not equal and false if they are equal.
"koan" != "discursive thought" # Output: => true
Note that two arrays with the same elements in a different order are not equal, uppercase and lowercase versions of the same letter are not equal and so on.
When comparing numbers of different types (e.g., integer and float), if their numeric value is the same, == will return true.
2 == 2.0 # Output: => true
Comparison operators
Objects such as numbers and strings, which can be compared (amongst themselves) in terms of being greater or smaller than others, provide the <=> method, also known as the spaceship method. When comparing two objects, <=> returns -1 if the first object is lesser than the second (a < b), 0 in case they are equal (a == b) and 1 when the first object is greater than the second (a > b).
5 <=> 8 # Output: => -1
5 <=> 5 # Output: => 0
8 <=> 5 # Output: => 1
Most comparable or sortable object classes, such as Integer, Float, Time and String, include a mixin called Comparable, which provides the following comparison operators: < (less than), <= (less than or equal), == (equal), > (greater than), >= (greater than or equal). These methods use the spaceship operator under the hood.
Comparison operators can be used in objects of all the above classes, as in the following examples.
# String
"a" < "b" # Output: => true
"a" > "b" # Output: => false
# Symbol
:a < :b # Output: => true
:a > :b # Output: => false
# Fixnum (subclass of Integer)
1 < 2 # Output: => true
2 >= 2 # Output: => true
# Float
1.0 < 2.0 # Output: => true
2.0 >= 2.0 # Output: => true
# Time
Time.local(2016, 5, 28) < Time.local(2016, 5, 29) # Output: => true
When comparing numbers of different classes, comparison operators will implicitly perform simple type conversions.
# Fixnum vs. Float
2 < 3.0 # Output: => true
2.0 > 3 # Output: => false
More info about Ruby operators is available at this blog post.

Resources