Reputation: 917
I have an array that looks like the following:
[
{ type: 'A', price: '0.01' },
{ type: 'B', price: '4.23' },
{ type: 'D', price: '2.29' },
{ type: 'B', price: '3.38' },
{ type: 'C', price: '1.15' }
]
I need to group these by type
and then sort them by ascending price
. I can half solve this problem by doing the following:
boards.sort_by {|e| [e['type'], e['price'].to_f]}
Unfortunately, this sorts the type
s alphabetically when they should be sorted BADC
How do I sort the array by the pre-determined rules?
Upvotes: 8
Views: 4407
Reputation: 2724
Your use of the term "group by" is confusing people.
If you want to sort by type, and if type is equal then sort by price, you can do this:
boards.sort do |a, b|
type_order = a[:type] <=> b[:type]
if type_order != 0
type_order
else
a[:price] <=> b[:price]
end
end
If not, you'll need to better explain what you want. :-)
Upvotes: 1
Reputation: 80095
ar=[
{ type: 'A', price: '0.01' },
{ type: 'B', price: '4.23' },
{ type: 'D', price: '2.29' },
{ type: 'B', price: '3.38' },
{ type: 'C', price: '1.15' }
]
SORT_ORDER = 'BADC' #could also be an array, eg ["monday", "tuesday", ...]
p ar.sort_by{|e| [SORT_ORDER.index(e[:type]), e[:price].to_f]}
Output:
[{:type=>"B", :price=>"3.38"},
{:type=>"B", :price=>"4.23"},
{:type=>"A", :price=>"0.01"},
{:type=>"D", :price=>"2.29"},
{:type=>"C", :price=>"1.15"}]
Upvotes: 14
Reputation: 67900
[edit] The question is not clear. That's what I understand: order boards by price ASC
but for boards of the same type, get only the cheapest. Using Facets' abstraction Enumerable#uniq_by (also in ActiveSupport: Array#uniq_by):
require 'facets'
boards.sort_by { |b| p[:price].to_f }.uniq_by { |b| b[:type] }
Output:
[{:type=>"A", :price=>"0.01"},
{:type=>"C", :price=>"1.15"},
{:type=>"D", :price=>"2.29"},
{:type=>"B", :price=>"3.38"}]
Upvotes: 2