RossyBergg
RossyBergg

Reputation: 161

Average values in an array of hashes with duplicate keys

I have an array of hashes set up as below:

array = [
  {"1" => 1, "2" => 2, "3" =>3},
  {"1" => 1, "2" => 2, "3" =>3}, 
  {"1" => 1, "2" => 2, "3" =>3}
]

I'm trying to find a way to average the values of all the hashes with key "1", for example.

Can someone help?

Upvotes: 3

Views: 158

Answers (5)

Sergio Belevskij
Sergio Belevskij

Reputation: 2967

array_data = [
  {"1" => 1, "2" => 2, "3" =>3}, 
  {"1" => 1, "2" => 2, "3" =>3}, 
  {"1" => 1, "2" => 2, "3" =>3}
]

class Hash
  def get_first
    self['1']
  end
end

class Array
  def avg
    sum / size
  end
end

avg = array_data.map(&:get_first).avg

Upvotes: 0

Sebastián Palma
Sebastián Palma

Reputation: 33491

Considering the Ruby version, yield_self (alias then) might work:

[{ "1" => 10, "2" => 2, "3" =>3 },
 { "1" => 43, "2" => 2, "3" =>3 },
 { "1" => 4, "2" => 2, "3" =>3 }].map { |hash| hash.fetch('1', 0) }.then { |arr| arr.sum.fdiv(arr.size) }
# 19.0

Where (10 + 43 + 4) / 3 = 19.0, not your example, but not just 1 + 1 + 1.

Upvotes: 2

steenslag
steenslag

Reputation: 80105

Array has a sum method nowadays, which takes a block. It basically sums whatever the block returns:

array = [{"1" => 0, "2" => 2, "3" =>3}, {"1" => 1, "2" => 4, "3" =>6}, {"1" => 2, "2" => 6, "3" =>9}]
array.sum{|h| h['1']}.fdiv(array.size)

Upvotes: 4

iGian
iGian

Reputation: 11203

Given the array (I changed the values for easy of debug):

array = [{"1" => 0, "2" => 2, "3" =>3}, {"1" => 1, "2" => 4, "3" =>6}, {"1" => 2, "2" => 6, "3" =>9}]

This code map each key to the average of values:

array.each_with_object(Hash.new{ |k,v| k[v] = [ ]}) { |h, hh| h.each { |k,v| hh[k] << v } }.transform_values { |k| k.sum.to_f/k.size }

#=>  {"1"=>1.0, "2"=>4.0, "3"=>6.0}


Methods used:

Upvotes: 0

spickermann
spickermann

Reputation: 107142

I would do something like this:

array = [{"1" => 1, "2" => 2, "3" =>3},{"1" => 1, "2" => 2, "3" =>3},{"1" => 1, "2" => 2, "3" =>3}]
array.map { |hash| hash['1'] }.inject { |sum, el| sum + el }.to_f / array.size
#=> 1.0

array.map { |hash| hash['1'] } extracts the values for all elements with the key '1' ([1,1,1]) in this example. And .inject{ |sum, el| sum + el }.to_f / array.size calculates the average.

Upvotes: 0

Related Questions