Как рассчитать средние значения в объектах, расположенных в массиве? - PullRequest
7 голосов
/ 09 марта 2012

Допустим, у меня есть такой массив:

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

Я хочу, чтобы у всех игроков было среднее количество голов за матч, а не среднее значение для каждого отдельного игрока, а общее среднее.

Я имею в виду сделать это с .each и сохранить каждое из отдельных средних значений, и в конце добавить их все и разделить на количество игроков, которые у меня есть. Тем не менее, я ищу Ruby / однострочный способ сделать это.

Ответы [ 4 ]

16 голосов
/ 09 марта 2012

По запросу, одна строка:

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 голос
/ 09 марта 2012

Небольшая модификация ответа токланда.

items.map{|e| e.values_at("goals", "number_of_matches")}.transpose.map{|e| e.inject(:+)}.instance_eval{|goals, matches| goals.to_f/matches}
0 голосов
/ 09 марта 2012

Чтобы сделать строку короче, давайте переименуем "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
0 голосов
/ 09 марта 2012
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.

...