Search code examples
rubyenumerable

Ruby 1.8.7: group_by with sum in an enumerable type


I have an array of records that is laid out in the following structure:

[{"some_id" => 2, "some_total => 250}, {"some_id" => 2, "some_total" => 100}, {"some_id" => 3, "some_total" => 50}, {"some_id" => 3, "some_total" => 50}, {"some_id" => 3, "some_total" => 25}, {"some_id" => 1, "some_total" => 10}]

What's the best way using Ruby's group_by/inject/sum or whatever is available with Enumerable, to have that return an ordered array of hashes, where each hash is keyed by "some_id" and the value is the sum of all that id's "some_total" ordered by the id with the highest total at the beginning of the array? The results would look like the following:

[{"some_id" => 2, "sum" => 350}, {"some_id" => 3, "sum => 125}, {"some_id" => 1, "sum" => 10}]


Solution

  • Functional approach:

    hs.group_by { |h| h["some_id"] }.map do |id, hs|
      sum = hs.map { |h| h["some_total"] }.inject(:+) 
      {:some_id => id, :sum => sum}
    end.sort_by { |h| -h[:sum] } 
    
    #=> [{:some_id=>2, :sum=>350}, 
    #    {:some_id=>3, :sum=>125}, 
    #    {:some_id=>1, :sum=>10}]