I want to specify a custom block method to sort an object array by evaluating two properties. However, after many searches, I didn't find to any example without the <=>
operator.
I want to compare a
to b
:
if a.x less than b.x return -1
if a.x greater than b.x return 1
if a.x equals b.x, then compare by another property , like a.y vs b.y
This is my code and it doesn't work:
ar.sort! do |a,b|
if a.x < b.y return -1
elseif a.x > b.x return 1
else return a.y <=> b.y
end
This block is within a function return
is exiting the function and returning -1
.
The Ruby sort method works by comparing elements of a collection using their <=> operator (more about that in a second), using the quicksort algorithm. You can also pass it an optional block if you want to do some custom sorting. The block receives two parameters for you to specify how they should be compared.
You can use the sort method on an array, hash, or another Enumerable object & you'll get the default sorting behavior (sort based on <=> operator) You can use sort with a block, and two block arguments, to define how one object is different than another (block should return 1, 0, or -1)
To sort a hash in Ruby without using custom algorithms, we will use two sorting methods: the sort and sort_by. Using the built-in methods, we can sort the values in a hash by various parameters.
This will give you ascending order for x
then for y
:
points.sort_by{ |p| [p.x, p.y] }
The best answer is provided by @AJcodez below:
points.sort_by{ |p| [p.x, p.y] }
The "correct" answer I originally provided, while it technically works, is not code I would recommend writing. I recall composing my response to fit the question's use of if
/else
rather than stopping to think or research whether Ruby had a more expressive, succinct way, which, of course, it does.
With a case
statement:
ar.sort do |a, b|
case
when a.x < b.x
-1
when a.x > b.x
1
else
a.y <=> b.y
end
end
With ternary:
ar.sort { |a,b| a.x < b.x ? -1 : (a.x > b.x ? 1 : (a.y <=> b.y)) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With