如何计算数组中对象的平均值?

时间:2012-03-09 18:38:29

标签: ruby average

假设我有一个这样的数组:

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

我希望所有球员的每场比赛的平均进球数,而不是每位球员的平均进球数,而是总平均值。

我想到了.each并存储了每个平均值,最后将它们全部加起来并除以我拥有的玩家数量。但是,我正在寻找一种Ruby /单行方式。

4 个答案:

答案 0 :(得分:16)

根据要求,单行:

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

更具可读性的代码段:

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

答案 1 :(得分:1)

对托克兰的回答稍作修改。

items.map{|e| e.values_at("goals", "number_of_matches")}.transpose.map{|e| e.inject(:+)}.instance_eval{|goals, matches| goals.to_f/matches}

答案 2 :(得分:0)

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

编辑重命名密钥和阻止参数以减少字数。对于那些关心的人。

首先,如果您要使用字符串作为键,则您的密钥需要使用=>

reduce将迭代数组并对每个玩家的各个平均值求和,最后我们将该结果除以总玩家数。括号中的“0”是reduce的起始编号。

答案 3 :(得分:0)

要缩短字符串,请将"number_of_matches"重命名为"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