Reputation: 155
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
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
Reputation: 1836
Take a look at Hash#transform_values. Also you can replace inject
with Array#sum.
hash.transform_values(&:sum)
Upvotes: 5