Feature #21157
openComparison operator <>
Description
I propose introducing a comparison operator <> which would give the following results:
1 <> 2 # => -1
2 <> 1 # => 1
1 <> 1 # => false
1 <> "a" # => true
With the help of the new operator, complex ordering expressions could be written explicitly. For example:
Point = Struct.new(:x, :y)
array = [Point.new(1, 2), Point.new(6, 4), Point.new(2, 2), Point.new(5, 2)]
array.sort{|a, b| a.y <> b.y || b.x <> a.x || 0 } # => [#<struct Point x=5, y=2>, #<struct Point x=2, y=2>, #<struct Point x=1, y=2>, #<struct Point x=6, y=4>]
The <>
notation may look familiar to sql users, where it means 'not equal'. Defined in the form given it will retain this meaning to some extent:
a = b = 1
a_not_equal_b if a <> b
a_equal_b unless a <> b
Updated by Hanmac (Hans Mackowiak) about 9 hours ago
Isn't it easier to use sort_by instead? And then use an Array as Sorting Field?
array.sort_by {|o| [o.y, -o.x] } #=> [#<struct Point x=5, y=2>, #<struct Point x=2, y=2>, #<struct Point x=1, y=2>, #<struct Point x=6, y=4>]
Updated by lpogic (Łukasz Pomietło) about 8 hours ago
I think that not having to create intermediate arrays and referencing the x coordinate when y is different would be an advantage.
Updated by P3t3rU5 (Pedro Miranda) about 8 hours ago
comparison operator already exists it's <=>
if you want a class to be comparable you just include the Comparable module and implement <=>
Updated by nobu (Nobuyoshi Nakada) about 7 hours ago
- Description updated (diff)
lpogic (Łukasz Pomietło) wrote:
I propose introducing a comparison operator <> which would give the following results:
1 <> 2 # => -1 2 <> 1 # => 1 1 <> 1 # => false 1 <> "a" # => true
I'm not sure what the last example means, maybe incomparable -> true?
With the help of the new operator, complex ordering expressions could be written explicitly. For example:
Point = Struct.new(:x, :y) array = [Point.new(1, 2), Point.new(6, 4), Point.new(2, 2), Point.new(5, 2)] array.sort{|a, b| a.y <> b.y || b.x <> a.x || 0 } # => [#<struct Point x=5, y=2>, #<struct Point x=2, y=2>, #<struct Point x=1, y=2>, #<struct Point x=6, y=4>]
array.sort{|a, b| (a.y <=> b.y).nonzero? || b.x <> a.x}
I agree that it would be a bit shorter/simpler, but I doubt it's worth adding new syntax.
The
<>
notation may look familiar to sql users, where it means 'not equal'.
Or BASIC users?
Anyway, <>
in SQL is a boolean operator and not expected returing ±1.
Updated by lpogic (Łukasz Pomietło) about 7 hours ago
P3t3rU5 (Pedro Miranda) wrote in #note-3:
comparison operator already exists it's
<=>
if you want a class to be comparable you just include the Comparable module and implement
<=>
<=>
is good enough for comparing a single property, e.g. a.y <=> b.y
. Things get complicated when we want to compare several consecutive properties, e.g.:
array.sort do |a, b|
result = a.y <=> b.y
result == 0 ? b.x <=> a.x : result
end
Including the Comparable
module simply moves this code to a different location. And this is only an option if we want to sort in natural order.
Updated by lpogic (Łukasz Pomietło) about 6 hours ago
nobu (Nobuyoshi Nakada) wrote in #note-4:
I'm not sure what the last example means, maybe incomparable -> true?
Yes, this is a case where objects are incomparable. I'm not sure if true
is the most appropriate value, but I don't have a better idea at the moment.
nobu (Nobuyoshi Nakada) wrote in #note-4:
array.sort{|a, b| (a.y <=> b.y).nonzero? || b.x <=> a.x}
This actually solves the presented problem in a relatively clear way. Until now I was not aware of the existence of nonzero?
.
nobu (Nobuyoshi Nakada) wrote in #note-4:
Or BASIC users?
Anyway,<>
in SQL is a boolean operator and not expected returing ±1.
Sure. I only see the similarity when <>
is used in logical expressions.
Updated by nobu (Nobuyoshi Nakada) about 6 hours ago
Tried an implementation: https://github.com/nobu/ruby/tree/ncmp