Sorting an array of arrays in Ruby
sort_by
Instead of using spaceship operator (<=>
) give a try to sort_by
device_array.sort_by { |el| el[4] }
Though if you know that the forth element is the last one, you can use el.last
too in the block.
Ruby docs: Enumerable#sort_by
I know the question has been answered, and I'm not going to address it now, but..
Are you sure an array would be the best fit for that data? I'm talking about these data elements: ["name1", "type1", ["A", "N", "N"], ["Attribute", "device_attribute"], 9]
Seems like a Struct or something might be more appropriate and manageable for this, and then you can have an array of Structs. Just an idea.
You can't use <=>
with nil
.
Your code should be something like this:
AllDevicesController.all_devices.sort do |a, b|
a[4].nil? ? -1 : b[4].nil? ? 1 : a[4] <=> b[4]
end
This will put the sub-arrays that have no element of index 4 at the beginning of the result. To do it the other way around, swap -1
with 1
.
You could also use sort_by
instead of sort
. I think this has been introduced in Ruby 1.8.7 (so it might not work if you are using an older version). It goes something like:
AllDevicesController.all_devices.sort_by { |e| e.nil? ? 0 : e[4] }
This will treat sub-arrays with no 4th element as if it was 0. Change this constant to suit you.
EDIT:
After you adjusted the input, it is now clear you were very close to the right answer. Your code should have been:
AllDevicesController.all_devices.sort do |a, b|
a[4] <=> b[4]
end
Or simple (assuming Ruby 1.8.7 or more):
AllDevicesController.all_devices.sort_by { |e| e[4] }
In both cases, the variables a
and b
will contain elements of the original array, this is why you can directly access an element in any position (and you don't need something like a[][4]
, which is incorrect Ruby syntax).
The 4th element is actually at index 3, which means you would do it like this:
all_devices.sort do |a, b|
a[3] <=> b[3]
end
If you really want to sort the elements at index 4 (which doesn't exist for the first element of all_devices
), then you need to add comparison to the NilClass first:
class NilClass
def <=> (other)
1
end
end
all_devices.sort do |a, b|
a[4] <=> b[4]
end
This will sort nil
to the end. Change the return value of <=>
to -1 to sort them to the front.