ruby sorting two arrays
a = [[0,1], [1,2], [2,3]]
b = [5, 3, 4]
a, b = b.zip(a).sort.transpose
p b #=> [[1, 2], [2, 3], [0, 1]]
To see how this works, just look at the result of p b.zip(a)
; then p b.zip(a).transpose
.
How to sort one array based on another array using Ruby
It perfectly works:
▶ A = [1,3,2,6,4,5,7,8,9,10]
▶ B = [3,4,1,5,2,6]
▶ B.sort_by &A.method(:index)
#⇒ [1, 3, 2, 6, 4, 5]
If there could be elements in B
that are not present in A
, use this:
▶ B.sort_by { |e| A.index(e) || Float::INFINITY }
How do I sort two arrays the same way?
You could combine both the arrays into one using the zip
method. Once you combine a and b, you would get,
[[6, 1], [4, 3], [3, 4]]
Now sort the arrays, which would sort them based on the first element of each sub-array resulting in,
[[3, 4], [4, 3], [6, 1]]
Now we want to do the reverse of zip to get the first and second elements of each sub-array into a new array. Using transpose
, we can get it back in the original form as,
[[3, 4, 6], [4, 3, 1]]
Thankfully using parallel assignment all of this is possible in one line. Here's the full code,
x, y = a.zip(b).sort.transpose
Now x
should contain [3, 4, 6]
, and y
should contain [4, 3, 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?
How to sort a hash by the values of another array in Ruby?
You don't need to sort anything, and you also don't need to create a lookup table. Your array is already sorted the way you want and your sort_me
hash is already a lookup table:
elements = ['one', 'two', 'three']
# => ["one", "two", "three"]
sort_me = {'three' => 3, 'two' => 2, 'one' => 1}
# => {"three"=>3, "two"=>2, "one"=>1}
elements.map{|key| [key, sort_me[key] ] }.to_h
# => {"one"=>1, "two"=>2, "three"=>3}
If you want to use symbols and strings:
elements = ['one', 'two', 'three']
# => ["one", "two", "three"]
sort_me = {three: 3, two: 2, one: 1}
# => {:three=>3, :two=>2, :one=>1}
elements.map{|key| [key.to_sym, sort_me[key.to_sym] ] }.to_h
# => {:one=>1, :two=>2, :three=>3}
Finally, if some elements
are not used in the hash, you could simply remove pairs with nil
values:
elements = ['one', 'two', 'two_and_a_half', 'three']
# => ["one", "two", "two_and_a_half", "three"]
elements.map{|key| [key.to_sym, sort_me[key.to_sym] ] }.to_h
# => {:one=>1, :two=>2, :two_and_a_half=>nil, :three=>3}
elements.map{|key| [key.to_sym, sort_me[key.to_sym] ] }.reject{|k, v| v.nil? }.to_h
# => {:one=>1, :two=>2, :three=>3}
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.
Ruby - How do I sort one array with another array using sort_by?
Sort by the index of the extensions array, then the filename:
filenames = ["z.pdf", "z.txt", "a.pdf", "z.rf", "a.rf","a.txt", "z.html", "a.html"]
extensions = ["html", "txt", "pdf", "rf"]
p sorted = filenames.sort_by{|fn| [extensions.index(File.extname(fn)[1..-1]), fn]} #[1..-1] chops off the dot
#=> ["a.html", "z.html", "a.txt", "z.txt", "a.pdf", "z.pdf", "a.rf", "z.rf"]
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).
Related Topics
Ruby/Rails - Active Record Db Migration to MySQL - Timestamp Type
Render Erb from Database into View Problem Please Help!
Ruby Implementation Win32API Get Mouse Scroll/Wheel Input
Devise 'Find_First_By_Auth_Conditions' Method Explanation
Ruby - Permutation Between Elements of an Array
Ruby Stack Failed to Deploy on Google Developers Console
Ruby Net-Ssh Calling Bash Script with Interactive Prompts
Ancestry Gem in Rails and Mutli Nesting
Are Spies an Appropriate Approach to See If Resque Methods Are Being Fired
Pass Ruby Script File to Rails Console
Using --No-Rdoc and --No-Ri with Bundler
How to Install Ruby Gems on MAC
Rails Get Index of "Each" Loop
Differencebetween 'Raise "Foo"' and 'Raise Exception.New("Foo")'
How to Install Nokogiri on MAC Os Sierra 10.12
Override Vagrant Configuration Settings Locally (Per-Dev)
Why Would We Put a Module Inside a Class in Ruby
How to Add 'Each' Method to Ruby Object (Or Should I Extend Array)