2

Following is an array of hashes:

array = [
  {loading: 10, avg: 15, total: 25 },
  {loading: 20, avg: 20, total: 40 },
  {loading: 30, avg: 25, total: 55 }
]

I need to sum the values of each hash and the result should be a hash of same keys:

{loading: 60, avg: 60, total: 120}

One way is to sum the values individually for each key and then merge in a hash like this:

loading = array.map { |h| h[:loading] }.sum
avg = array.map { |h| h[:avg] }.sum
total = array.map { |h| h[:total] }.sum

{loading: loading, avg: avg, total: total}

Is there a better way to do it? because the keys may increase in the future.

Arif
  • 1,369
  • 14
  • 39

1 Answers1

10

You could use each_with_object with a Hash and a default value:

array = [
  {loading: 10, avg: 15, total: 25 },
  {loading: 20, avg: 20, total: 40 },
  {loading: 30, avg: 25, total: 55 }
]

sum = Hash.new(0)

array.each_with_object(sum) do |hash, sum|
  hash.each { |key, value| sum[key] += value }
end
 # => {:loading=>60, :avg=>60, :total=>120}

It will work with any number of keys, and won't complain if a key isn't present in all the hashes.


BTW, you can replace

array.map { |h| h[:loading] }.sum

with

array.sum { |h| h[:loading] }
ndnenkov
  • 35,425
  • 9
  • 72
  • 104
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124