Reduce Hash Values
I know I'm excavating this one, but if you happen to use Rails, the .sum
method can help:
H = {"Key1" => 1, "Key2" => 2}
=> {"Key1"=>1, "Key2"=>2}
> H.values.sum
=> 3
Advantage is that it returns 0
on empty hashes:
> {}.values.sum
=> 0
> {}.values.reduce(:+)
=> nil
I noticed it was Rails-specific only after typing this answer. I know the OP didn't add the Rails tag, but I figured it might be useful for people stopping by.
Note that as of Ruby 2.4.0, .sum
is now available.
You can make elem
contain the value by splitting it up in 2 variables:
H.reduce(0) {|memo, (key, val)| memo + val}
Use Enumerable#reduce
, if you're ok with getting nil
if the hash happens to be empty:
H.values.reduce(:+) # => 3
Hash.new.values.reduce(:+) # => nil
To safely get 0
when the hash is empty, use:
H.values.reduce(0) { |sum,x| sum + x } # or...
H.reduce(0) { |sum,(key,val)| sum + val } # ...if you need to inspect the key
Here's a quick benchmark, for kicks. Note that it appears to be slightly faster to reduce just the values rather than values from the key/value pairs:
user system total real
H.values.reduce(:+) 4.510000 0.080000 4.590000 ( 4.595229)
H.values.reduce(0) {...} 4.660000 0.080000 4.740000 ( 4.739708)
H.reduce(0) {...} 5.160000 0.070000 5.230000 ( 5.241916)
require 'benchmark'
size = 1_000
hash = Hash[* Array.new(size*2) { rand } ]
N=10_000
Benchmark.bm(24) do |x|
x.report('H.values.reduce(:+)') { N.times { hash.dup.values.reduce(:+) } }
x.report('H.values.reduce(0) {...}') { N.times { hash.dup.values.reduce(0) { |sum,x| sum + x } } }
x.report('H.reduce(0) {...}') { N.times { hash.dup.reduce(0) { |sum,(_,v)| sum + v } } }
end
Try this:
H.reduce(0) { |memo, elem| memo += elem[1] }
or
H.reduce(0) { |memo, (key, value)| memo += value }