Reputation: 69
in a Ruby program I have an hash which has normal strings as keys and the values are array of numbers:
hash_1 = {"Luke"=> [2,3,4], "Mark"=>[3,5], "Jack"=>[2]}
And what I'm looking for is to have as result the same hash with the values that become the average of the numbers inside the arrays:
{"Luke"=> 3, "Mark"=>4, "Jack"=>2}
One way to make it to work can be to create a new empty hash_2, loop over hash_1 and within the block assign the keys to hash_2 and the average of the numbers as values.
hash_2 = {}
hash_1.each do |key, value|
hash_2[key] = value.sum / value.count
end
hash_2 = {"Luke"=> 3, "Mark"=>4, "Jack"=>2}
Is there a better way I could do this, for instance without having to create a new hash?
Upvotes: 0
Views: 333
Reputation: 110645
def avg(arr)
return nil if arr.empty?
arr.sum.fdiv(arr.size)
end
h = { "Matthew"=>[2], "Mark"=>[3,6], "Luke"=>[2,3,4], "Jack"=>[] }
h.transform_values { |v| avg(v) }
#=> {"Matthew"=>2.0, "Mark"=>4.5, "Luke"=>3.0, "Jack"=>nil}
Upvotes: 2
Reputation: 857
This solution is different than the one that use transform_values!
because return a new Hash object.
hash_1.map { |k,v| [k, v.sum / v.size] }.to_h
Upvotes: 0
Reputation: 2829
@Виктор OK. How about this:
hash_1 = {"Luke"=> [2,3,4], "Mark"=>[3,5], "Jack"=>[2], "Bobby"=>[]}
hash_2 = hash_1.reduce(Hash.new(0)) do |acc, (k, v)|
v.size > 0 ? acc[k] = v.sum / v.size : acc[k] = 0
acc
end
p hash_2
Upvotes: 0
Reputation: 6064
hash_1 = {"Luke"=> [2,3,4], "Mark"=>[3,5], "Jack"=>[2]}
You don't need another hash for the given below code.
p hash_1.transform_values!{|x| x.sum/x.count}
Result
{"Luke"=>3, "Mark"=>4, "Jack"=>2}
Upvotes: 5