Sorting an array of arrays in Ruby
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).
ruby sort array of an array
Try either:
array = [["happy", 1], ["sad", 2], ["mad", 1], ["bad", 3], ["glad", 12]]
sorted = array.sort {|a,b| a[1] <=> b[1]}
Or:
array = [["happy", 1], ["sad", 2], ["mad", 1], ["bad", 3], ["glad", 12]]
sorted = array.sort {|a,b| b[1] <=> a[1]}
Depending if you want ascending or descending.
Ruby sort array of arrays by subindex alphabetically
If the index is 3
, then:
arr_of_arrs.sort_by{|a| a[3]}
Sorting array of arrays on column
Use Enumerable#sort_by
:
customers.sort_by { |e| -e[2] }
=> [[8, "Customer B", 264509.0],
[439, "Customer A", 60800.0],
[546, "Customer C", 17900.0]]
Sorting Ruby array of array items by length evenly
The algorithm I would use to get a roughly even distribution of size, per my comment on OP:
unchunked_data = [
[{...}],
[{...}],
[{...}],
[{...}],
[{...}],
[{...}],
[{...}],
[{...}]
]
sorted_data = unchunked_data.sort_by(&:size)
grouped_data = sorted_data.each_with_index.group_by { |_, index| index % 4 }
grouped_data.each do |process_index, data|
# each_with_index would put data in an array with its index in sorted_data. Calling map(&:first) removes that index.
data_without_index = data.map(&:first)
send_data_to_process(process_index, data_without_index)
end
If the data is as it appears in OP's example, this results in a perfect distribution.
Per discussion in the comments, you can get back all the data in single array, as formatted in the original but grouped with this method, by doing:
grouped_data.values.flatten(1)
how to sort an array of arrays by three or more elements (ruby)
This:
array_of_arrays = [[1,9,'a'],[2,2,'a'], [2,6,'b'], [1,3,'a'], [2,1,'b']]
array_of_arrays.each {|line| p line }
puts
array_of_arrays.sort_by {|e| [e[2], e[0], e[1]]} .each {|line| p line }
Produces the following output for me:
[1, 3, "a"]
[1, 9, "a"]
[2, 2, "a"]
[2, 1, "b"]
[2, 6, "b"]
That's what you want, right?
Ruby Sort an array of arrays of numbers based on multiple conditions
My understanding is that when a[2] >= 0
, sorting is to on the array [a[1], a[2]]
, and elements for which a[2] < 0
are to be at the end of the sorted array and sorted by [-a[1], -a[2]]
.
biggest_plus_1 = to_sort.map { |a| a[2] }.max + 1
#=> 3
to_sort.sort_by { |a| a[2] >= 0 ? [0, a[1], a[2]] : [biggest_plus_1, -a[1], -a[2]] }
#=> [[6, 27, 1, 11.0], [7, 27, 1, 12.0], [8, 27, 1, 13.0], [9, 27, 2, 14.0],
# [5, 27, -2, 5.0], [2, 27, -2, 2.0], [3, 27, -2, 3.0], [4, 27, -2, 4.0],
# [1, 27, -3, 1.0]]
Array#sort and Enumerable#sort_by rely on the method Array#<=> for determining the ordering of each pair of arrays being sorted. Two arrays, a
and b
are ordered lexicographically, meaning the following. If a[0] < b[0]
then a
is less than b
(a < b
), or equivalently, a <=> b #=> -1
. Similarly, if a[0] > b[0]
then a
is greater than b
(a > b
) and a <=> b #=> 1
. If a[0] == b[0]
, the tie is broken by the comparing the second elements in the same way, and so on. If a
is smaller than b
(a.size < b.size
), and the first a.size
elements of each array are equal, a < b
. a
and b
are equal if and only if a <=> b #=> 0
.
Since elements a
for which a[2] < 0
are to be placed at the end of the sorted array, we need to sort by arrays whose first elements place the array at the front or back of the sorted array. It is for that reason that I made the first element of the sort-by array zero when a[2] >= 0
and biggest_plus_1
when a[2] < 0
, where biggest_plus_1
is the largest value of a[2]
plus 1.
The remaining elements of the sort-by arrays determine how each of the two groups of arrays are to be sorted.
Note that biggest_plus_1
will be non-positive if all a[2] < 0
, but that doesn't matter, as no element will be sorted by an array whose first element is zero.
Sort an array of arrays based on the order in another array
h = x.to_h
# => {"ready"=>5,
# "shipped"=>1,
# "pending"=>1,
# "refunded"=>1,
# "delivered"=>23,
# "scheduled"=>1,
# "canceled"=>51}
order_array.map{|key| [key, h[key]] if h.key?(key)}.compact
# => [["ready", 5],
# ["shipped", 1],
# ["scheduled", 1],
# ["delivered", 23],
# ["canceled", 51],
# ["refunded", 1]]
or
h = x.to_h{|k, v| [k, [k, v]]}
#=> {"ready"=>["ready", 5],
# "shipped"=>["shipped", 1],
# "pending"=>["pending", 1],
# "refunded"=>["refunded", 1],
# "delivered"=>["delivered", 23],
# "scheduled"=>["scheduled", 1],
# "canceled"=>["canceled", 51]}
order_array.map{|k| h[k]}.compact
#=> [["ready", 5],
# ["shipped", 1],
# ["scheduled", 1],
# ["delivered", 23],
# ["canceled", 51],
# ["refunded", 1]]
or
h = x.to_h{|k, v| [k, [k, v]]}
#=> {"ready"=>["ready", 5],
# "shipped"=>["shipped", 1],
# "pending"=>["pending", 1],
# "refunded"=>["refunded", 1],
# "delivered"=>["delivered", 23],
# "scheduled"=>["scheduled", 1],
# "canceled"=>["canceled", 51]}
h.values_at(*order_array).compact
#=> [["ready", 5],
# ["shipped", 1],
# ["scheduled", 1],
# ["delivered", 23],
# ["canceled", 51],
# ["refunded", 1]]
Ruby Sort Array of Arrays by Child Element
You can pass a block to the sort method like this:
array.sort { |a, b| b[1] <=> a[1] }
Related Topics
How to Access a Variable Within a Heredoc in Ruby
What the Purpose of Bind/Unbind Methods in Ruby
Access Translation File (I18N) from Inside Rails Model
Form_For with Multiple Controller Actions for Submit
How to Return Everything After Last Slash(/) in a Ruby String
How to Pass Named Arguments to a Rake Task
Make Text Input Fields and Their Labels Line Up Correctly
Error Nomethoderror: Undefined Method 'Debug_Rjs=' for Actionview::Base:Class
"Cannot Load Such File - Rubygems/Defaults/Operating_System" When Installing Ruby 2.0.0
Using %I and %I Symbol Array Literal
How to Remove All Characters in a String Until a Substring Is Matched, in Ruby
Ror, Can't Iterate from Datetime/Timewithzone
Unwanted Form Parameters Being Appended to Pagination Links
Best Way to Remove File Extension