Data Don
Data Don

Reputation: 338

Sort array with custom order

I have an array of ids order say

order = [5,2,8,6]

and another array of hash

 [{id: 2,name: name2},{id: 5,name: name5}, {id: 6,name: name6}, {id: 8,name: name8}]   

I want it sorted as

[{id: 5,name: name5},{id: 2,name: name2}, {id: 8,name: name8}, {id: 6,name: name6}] 

What could be best way to implement this? I can implement this with iterating both and pushing it to new array but looking for better solution.

Upvotes: 3

Views: 2710

Answers (2)

Marian13
Marian13

Reputation: 9238

Enumerable#in_order_of (Rails 7+)


Starting from Rails 7, there is a new method Enumerable#in_order_of.

A quote right from the official Rails docs:

in_order_of(key, series)

Returns a new Array where the order has been set to that provided in the series, based on the key of the objects in the original enumerable.

[ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
=> [ Person.find(1), Person.find(5), Person.find(3) ]

If the series include keys that have no corresponding element in the Enumerable, these are ignored. If the Enumerable has additional elements that aren't named in the series, these are not included in the result.


It is not perfect in a case of hashes, but you can consider something like:

require 'ostruct'

items = [{ id: 2, name: 'name2' }, { id: 5, name: 'name5' }, { id: 6, name: 'name6' }, { id: 8, name: 'name8' }]

items.map(&OpenStruct.method(:new)).in_order_of(:id, [5,2,8,6]).map(&:to_h)
# => [{:id=>5, :name=>"name5"}, {:id=>2, :name=>"name2"}, {:id=>8, :name=>"name8"}, {:id=>6, :name=>"name6"}]

Sources:

Upvotes: 1

Alok Anand
Alok Anand

Reputation: 3356

Try this

arr = [  
         {:id=>2, :name=>"name2"}, {:id=>5, :name=>"name5"}, 
         {:id=>6, :name=>"name6"}, {:id=>8, :name=>"name8"}
      ]

order = [5,2,8,6]

arr.sort_by { |a| order.index(a[:id]) }
# => [{:id=>5, :name=>"name5"}, {:id=>2, :name=>"name2"}, 
#{:id=>8, :name=>"name8"}, {:id=>6, :name=>"name6"}] 

Upvotes: 9

Related Questions