How to Sort an Array in Ruby to a Particular Order

How to sort an array in Ruby to a particular order?

Array#sort_by is what you're after.

a.sort_by do |element|
b.index(element)
end

More scalable version in response to comment:

a=["one", "two", "three"]
b=["two", "one", "three"]

lookup = {}
b.each_with_index do |item, index|
lookup[item] = index
end

a.sort_by do |item|
lookup.fetch(item)
end

Ruby : How to sort an array of hash in a given order of a particular key

Here is a solution for any custom index:

def my_index x 
# Custom code can be added here to handle items not in the index.
# Currently an error will be raised if item is not part of the index.
[1,3,5,7,9,2,4,6,8,10].index(x)
end

my_collection = [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]
p my_collection.sort_by{|x| my_index x['id'] } #=> [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]

Then you can format it in any way you want, maybe this is prettier:

my_index = [1,3,5,7,9,2,4,6,8,10]
my_collection.sort_by{|x| my_index.index x['id'] }

Sort array using custom sorting preferences?

This is a task for group_by and values_at:

ORDER = %w[Orange Yellow Blue]
ary = [['Red','Blue'],['Green','Orange'],['Purple','Yellow']]

ary.group_by{ |a| a.last }.values_at(*ORDER)
# => [[["Green", "Orange"]], [["Purple", "Yellow"]], [["Red", "Blue"]]]

Here's what group_by brings to the party:

ary.group_by{ |a| a.last }
# => {"Blue"=>[["Red", "Blue"]],
# "Orange"=>[["Green", "Orange"]],
# "Yellow"=>[["Purple", "Yellow"]]}

Once you have the hash of values used to group each array, then values_at makes it easy to extract them in the right order.

This is an extremely fast and efficient way to do the task as it will barely slow down as ary grows due to the fact that there is no real sorting going on, it's just grouping by a value, then extracting from the hash in a given order.

If you want the exact same array-of-arrays as in your example, flatten the result once:

ary.group_by{ |a| a.last }.values_at(*ORDER).flatten(1)
# => [["Green", "Orange"], ["Purple", "Yellow"], ["Red", "Blue"]]

You won't want to do that if there are going to be multiple "Orange", "Yellow" or "Blue" elements as the result won't be very usable.

ruby/rails sort an array of records based on an array of string

You can do as

users.sort_by { |u| priority.index(u.priority) || priority.size }

The above sorting is done, with the assumption that the below Array will be sorted as per your need, will hold all uniq values. users array then will use the index of the sorted array.

priority = ["Wednesday","Tuesday","Friday"]

index(obj) → int or nil

Returns the index of the first object in ary such that the object is == to obj. Returns nil if no match is found.

priority array doesn't hold all weekdays, rather 3. I thought, if any users has priority, which is not present in the priority array, let those users be placed in the last array. Suppose, for any user there is a priority, "Sunday", then, that user will be given lowest priority. How ?

Look at the expression priority.index(u.priority) || priority.size, now with above mentioned sample, priority.index("sunday") gives nil, and right hand side expression of the || will be evaluated, i.e. priority.size, which 3. That's how that user will be moved to the tail of the array.

Ruby on Rails - How to arrange elements of array in particular order

As others have said, you cannot do that with Ruby 1.87 or prior. Here is one way to do that with Ruby 1.9+:

arr = [{:age=>28, :name=>"John", :id=>1}, {:name=>"David", :age=>20, :id=>2}]
order = [:id, :name, :age]

arr.map { |h| Hash[order.zip(h.values_at(*order))] }
#=> [{:id=>1, :name=>"John", :age=>28}, {:id=>2, :name=>"David", :age=>20}]

In Ruby 2.0+, you can write:

arr.map { |h| order.zip(h.values_at(*order)).to_h }

I thought 1.8.7 went out with the steam engine.

How to sort only specific elements in an array?

Possible solution

ary = [3, "foo", 2, 5, "bar", 1, "baz", 4]

integers = ary.select(&->(el) { el.is_a?(Integer) }).sort
ary.map { |n| n.is_a?(Integer) ? integers.shift : n }

# => [1, "foo", 2, 3, "bar", 4, "baz", 5]

Is there a way to sort countries in Rails based on a particular order?

Building on Stefan's comment, we can first sort by the release year, then a special country order, then by the country itself.

class Version
SPECIAL_COUNTRY_ORDER = ["UK", "US", "DE", "FR", "JP"]

attr_accessor :country_code, :release_year

def initialize(country_code:, release_year:)
@country_code = country_code
@release_year = release_year
end

def special_country_order
SPECIAL_COUNTRY_ORDER.index(country_code) || SPECIAL_COUNTRY_ORDER.size
end

def to_s
"#{country_code} #{release_year}"
end
end

versions = [
Version.new(country_code: "DE", release_year: 1969),
Version.new(country_code: "UK", release_year: 1969),
Version.new(country_code: "JP", release_year: 1999),
Version.new(country_code: "AA", release_year: 1999),
Version.new(country_code: "BB", release_year: 1999),
Version.new(country_code: "ZZ", release_year: 1999),
Version.new(country_code: "BB", release_year: 2000)
]

puts versions.sort_by { |version|
[version.release_year, version.special_country_order, version.country_code]
}

If a country doesn't have a special country order it gets a number greater than any of the special countries. Since it's greater it sorts below them. Since it's the same number the sort moves on to the next sort key: the country code itself.

Here's what it's sorting by.

[1969, 2, "DE"]
[1969, 0, "UK"]
[1999, 4, "JP"]
[1999, 5, "AA"]
[1999, 5, "BB"]
[1999, 5, "ZZ"]
[2000, 5, "BB"]

And the result.

UK 1969
DE 1969
JP 1999
AA 1999
BB 1999
ZZ 1999
BB 2000


Related Topics



Leave a reply



Submit