purinkle
purinkle

Reputation: 917

How do I perform a complex custom sort in Ruby?

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 types alphabetically when they should be sorted BADC

How do I sort the array by the pre-determined rules?

Upvotes: 8

Views: 4407

Answers (3)

sheldonh
sheldonh

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

steenslag
steenslag

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

tokland
tokland

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

Related Questions