1, "number_of_matches" => 2, ...">

How to calculate average values ​​in objects located in an array?

Say I have an array like this:

[ { "player_id" => 1, "number_of_matches" => 2, "goals" => 5 }, { "player_id" => 2, "number_of_matches" => 4, "goals" => 10 } ] 

I want to have average goals per match among all players, not the average for each individual player, but the overall average.

I mean to do this with .each and save each of the separate averages, and at the end add them all and divide by the number of players that I have. However, I am looking for a way for Ruby / one-liner to do this.

+7
source share
4 answers

As per request single line:

 avg = xs.map { |x| x["goals"].to_f / x["number_of_matches"] }.reduce(:+) / xs.size 

More readable snippet:

 goals, matches = xs.map { |x| [x["goals"], x["number_of_matches"]] }.transpose avg = goals.reduce(:+).to_f / matches.reduce(:+) if goals 
+16
source

A slight modification tokland's answer.

 items.map{|e| e.values_at("goals", "number_of_matches")}.transpose.map{|e| e.inject(:+)}.instance_eval{|goals, matches| goals.to_f/matches} 
+1
source
 a = [{player_id:1 , match_num:2, goals: 5}, {player_id:2 , match_num:4, goals: 10}] a.reduce(0){|avg, p| avg += p[:goals].to_f/p[:match_num]}/a.size 

Edit: renamed keys and block arguments to decrease char counter. For those who care.

First, your keys should use => if you are going to use strings as keys.

reduce will reduce over the array and summarize the individual averages for each player, and finally, we divide this result by the number of players. The "0" in parentheses is your starting number for reduce .

0
source

Rename the "number_of_matches" to "matches" to make the line shorter "matches"

 a = [ {"player_id":1 , "matches":2, "goals": 5}, {"player_id":2 , "matches":4, "goals": 10} ] a.reduce([0,0]){|sum,h|[sum.first+h["goals"],sum.last+h["matches"]]}.reduce{|sum,m|sum.to_f/m} #=> 2.5 
0
source

All Articles