- 1
✩
0
Группировка хешей в руби
Допустим, есть такой хеш:
h={
2010-03-01=>2
2010-03-02=>4
2010-03-03=>1
..
..
рабочий_день=>кол_во_часов
}
где каждый ключ представляет собой дату, а значение - целое число (кол-во проработанных часов в этот день). Как трансформировать этот хеш в новый, чтобы ключи хеша были неделями/месяцами/годами, а значения - суммами проработанных часов в этом периоде?
Пример того, как это должно выглядеть:
Недели:
h_weeks={7=>36, 8=>42, 9=>34 ..,..,n}
Если месяцы:
h_months={1=>170, 2=>180, 3=>146}
Если годы:
h_years={2009=>950, 2010=>446}
Спасибо
300
2 ответа:
-
- 1
h = { Date.parse('2010-04-02') => 3, Date.parse('2010-05-03') => 5, Date.parse('2009-04-03') => 6 } by_year = Hash.new(0) by_month = Hash.new(0) by_week = Hash.new(0) h.each{|d,v| by_year[d.year] += v by_month[d.month] += v by_week[d.cweek] += v }или более экзотический вариант:
aggregates = {} h.each{|d,v| [:year, :month, :cweek].each{|period| aggregates[period] ||= Hash.new(0) aggregates[period][d.send(period)] += v } } p aggregates #=>{:year=>{2010=>8, 2009=>6}, :month=>{4=>9, 5=>5}, :cweek=>{13=>3, 18=>5, 14=>6}}Я просто не знаком с ruby, вы не против?
-
- 0
Хардкорные однострочники на Ruby:
#Для недель weeks = days.inject({}) { |w, d| w[d.first.cweek].nil? ? w[d.first.cweek] = d.last : w[d.first.cweek] = w[d.first.cweek] + d.last; w } #По годам years = days.inject({}) { |y, d| y[d.first.year].nil? ? y[d.first.year] = d.last : y[d.first.year] = y[d.first.year] + d.last; y }Приличный метод для сбора статистики (полный код, тестировал только на Ruby 1.9):
require "date" require "pp" days = { Date.parse("2009-04-12") => 10, Date.parse("2010-04-12") => 20, Date.parse("2010-04-13") => 6, Date.parse("2010-04-14") => 1, Date.parse("2010-04-15") => 18, Date.parse("2010-04-16") => 0, Date.parse("2010-04-17") => 10, Date.parse("2010-04-18") => 2, Date.parse("2010-04-19") => 6, Date.parse("2010-04-20") => 3 } def collect_stats data data.inject({}) do |stats, data| #Key of array is obviously a date object next unless data.first.kind_of? Date #Initializes year stats storage stats[data.first.year] = {:overall => 0, :weeks => {}} if stats[data.first.year] == nil #Appends stats regarding year (it will be filled under the 'overall' key) stats[data.first.year][:overall] += data.last #Appends stats regarding weeks stats[data.first.year][:weeks][data.first.cweek] += data.last rescue stats[data.first.year][:weeks][data.first.cweek] = data.last #Returns all data back to the user stats end end pp collect_stats days #=> {2009=>{:overall=>10, :weeks=>{15=>10}}, #=> 2010=>{:overall=>66, :weeks=>{15=>57, 16=>9}}}
Чтобы написать ответ, вы должны авторизироваться.