rpg
rpg

Reputation: 155

How to sum an array of values within a single key of a hash?

Should be quick one! Couldn't quite find the exact query elsewhere:

I have a hash in the form:

{"Chicago"=>[35.0, 5.0, 7.0], "Austin"=>[12.0, 42.0, 15.0, 8.0], ... }

I simply want to sum the numbers within the hash's value (array) to become:

{"Chicago"=> 47.0, "Austin"=> 77.0, ... }

I have tried sum and inject (hash.values.each.inject(0) { |sum, x| sum + x} etc.) and am met with "Array cannot be coerced into Integer" exceptions, and I'm not sure the correct way to go about this, though it seems a relatively simple ask!

Upvotes: 1

Views: 134

Answers (2)

Tom Lord
Tom Lord

Reputation: 28305

Following your original approach, here is a full working solution -- it looks like you were on the right lines!

hash = {"Chicago"=>[35.0, 5.0, 7.0], "Austin"=>[12.0, 42.0, 15.0, 8.0]

hash.map { |city, values| [city, values.inject(0){ |sum, value| sum + value}] }.to_h

Phew! But that looks a bit complicated! Luckily for starters, you can call inject with a symbol that names an operator to shorten it a little:

hash.map { |city, values| [city, values.inject(:+)] }.to_h

Or even better, you can call Array#sum to achieve the same thing in this case:

hash.map { |city, values| [city, values.sum] }.to_h

We can still do better, though. For this very common use-case of only needing to transform hash values, whilst preserving the overall hash structure, modern ruby has a builtin method for this called ... you guessed it, transform_values:

hash.transform_values { |values| values.sum }

And finally, simplifying this one last time:

hash.transform_values(&:sum)

Upvotes: 2

yzalavin
yzalavin

Reputation: 1836

Take a look at Hash#transform_values. Also you can replace inject with Array#sum.

hash.transform_values(&:sum)

Upvotes: 5

Related Questions