I need to sum values in an array hashes and I found a way to do it here
but it sure seems like there should be a more elegant way in Ruby.
Here is what works;
sales = [{"sale_price"=>210000, "deed_type"=>"Warranty Deed"}, {"sale_price"=>268300, "deed_type"=>"Warranty Deed Joint"}]
total_sales = sales.inject(0) {|sum, hash| sum + hash["sale_price"]}
The totals line is not very readable. It would be nice if something like this worked;
total_sales = sales.sum("sale_price")
Is this just wishful thinking or am I overlooking a better solution?
I like using the map/reduce metaphor like so:
total_sales = sales.map {|s| s['sale_price']}.reduce(0, :+)
The reduce method is a synonym for the inject method, I find the name inject to be somewhat confusing with the memo component. It has another form I use above to take the initial value and a reference to a method call used for the combination/reduction process.
I think the overall pattern of mapping the values and then reducing them to an aggregate is well known and self-documenting.
EDIT: Use symbol :+ instead of proc reference &:+
You can make it work:
sales = [{"sale_price"=>210000, "deed_type"=>"Warranty Deed"}, {"sale_price"=>268300, "deed_type"=>"Warranty Deed Joint"}]
def sales.sum(by)
inject(0){|sum, h| sum + h[by]}
end
p sales.sum("sale_price") #=> 478300
Note this sum
method (sum_by might be a better name) is not defined on Array, but only on the specific sales array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With