How do I order an array in ruby ββwhen the order has four different conditions?
I'm not sure how I can reorder an array based on two booleans in Ruby. I would like to order my results in the following order:
* Note awkward ordering *
1) is_strong: true, requires_api_check: false
2) is_strong: true, requires_api_check: true
3) is_strong: false, requires_api_check: true
4) is_strong: false, requires_api_check: false
And I wrote some pseudo code to get it back in the correct order, but it doesn't work. I realize I can only return -1,0, + 1, but I'm not sure how to handle this situation.
objects = [
OpenStruct.new(is_strong: false, requires_api_check: false),
OpenStruct.new(is_strong: false, requires_api_check: true),
OpenStruct.new(is_strong: true, requires_api_check: false),
OpenStruct.new(is_strong: true, requires_api_check: true),
]
objects.sort do |res|
if res.is_strong
if !res.requires_api_check
1
else
2
end
else
if res.requires_api_check
3
else
4
end
end
end
source to share
Just use sort_by
which is available in arrays via Enumerable .
sort
gives two compare objects with a block and expects a value < 0
, 0
or > 0
. This allows you to define custom sorting rules between potentially unrelated objects.
sort_by
on the other hand, gives only one object to a block. Anything that is returned from the block is then used for comparison. If you return integers, your final array will be sorted by those raw Integer values.
So, given your "awkward" sorting rules, your code works great if you use sort_by
instead sort
, without having to express your rules in terms of spaceship rules .
In the example below, I have shortened your code a bit with ternary operators.
objects.sort_by do |res|
if res.is_strong
res.requires_api_check ? 2 : 1
else
res.requires_api_check ? 3 : 4
end
end
source to share
Since there doesn't seem to be any perceived logic, hardcoding AWKWARD_ORDERING is the way to go:
require "ostruct"
AWKWARD_ORDERING = [[true, false],[true,true],[false,true],[false, false]]
objects = [
OpenStruct.new(is_strong: false, requires_api_check: false),
OpenStruct.new(is_strong: false, requires_api_check: true),
OpenStruct.new(is_strong: true, requires_api_check: false),
OpenStruct.new(is_strong: true, requires_api_check: true),
]
p res = objects.sort{|obj| AWKWARD_ORDERING.index([obj.is_strong, obj.requires_api_check])}
source to share