按周/月选择和求和值

时间:2014-03-27 16:17:45

标签: ruby-on-rails ruby hash

我有一个日期和数量的哈希值如下:

{
  "2014-01-30"=>200.1, 
  "2014-02-01"=>27.86, 
  "2014-02-02"=>55.72, 

  "2014-02-03"=>83.58, 
  "2014-02-04"=>83.58, 
  "2014-02-05"=>76.41, 
  "2014-02-06"=>187.85, 
  "2014-02-07"=>27.86, 
  "2014-02-08"=>27.86, 
  "2014-02-09"=>55.72, 

  "2014-02-10"=>269.34, 
  "2014-02-11"=>83.58, 
  "2014-02-12"=>159.99, 
  "2014-02-13"=>373.61, 
  "2014-02-14"=>264.26, 
  "2014-02-15"=>236.4, 

  "2014-02-17"=>215.71, 
  "2014-02-18"=>55.72, 
  "2014-02-19"=>132.13, 
  "2014-02-20"=>104.27, 
  "2014-02-21"=>83.58, 
  "2014-02-22"=>104.27, 
  "2014-02-23"=>159.99, 

  "2014-02-24"=>27.86, 
  "2014-02-25"=>172.24, 
  "2014-02-27"=>380.78, 
  "2014-02-28"=>336.82, 
  "2014-03-01"=>55.72, 
  "2014-03-02"=>83.58, 

  "2014-03-03"=>83.58, 
  "2014-03-04"=>224.02, 
  "2014-03-05"=>574.76, 
  "2014-03-06"=>853.14, 
  "2014-03-07"=>27.86, 
  "2014-03-09"=>83.58, 

  "2014-03-10"=>241.48, 
  "2014-03-11"=>208.54, 
  "2014-03-12"=>368.53, 
  "2014-03-13"=>941.42, 
  "2014-03-14"=>396.39, 
  "2014-03-15"=>320.71, 
  "2014-03-16"=>144.38, 

  "2014-03-17"=>215.71, 
  "2014-03-18"=>83.58, 
  "2014-03-19"=>227.44, 
  "2014-03-20"=>104.27, 
  "2014-03-21"=>111.32, 
  "2014-03-22"=>104.27, 
  "2014-03-23"=>238.86, 

  "2014-03-25"=>172.24
}

我想要做的是将这些日期映射到"周"和"月"小组并将金额加起来。

因此,基本上取出开始日期和结束日期(在本例中为2014-01-302014-03-25),然后将其划分为日历周期和月期,并将所有天数总和那范围。

在上面的示例数据中,您会将其分为实际周数。请注意,其中一些分组只有6个项目,因为其中一天没有金额。

对于输出,我想要一个每周/每月范围总和数量的数组。

上述示例数据的输出为:[283.68, 542.86, 1387.18, 855.67, 1057.00, 1846.94, 2621.45, 1085.45, 172.24]

FWIW,我正在起诉Ruby 2和Rails 4。

2 个答案:

答案 0 :(得分:3)

# This for using outside Rails, remove if on Rails
require 'date'
gem 'activesupport'
require 'active_support/core_ext/date'
require 'active_support/core_ext/enumerable'

hash = {
  "2014-01-30"=>200.1, 
  "2014-02-01"=>27.86, 
  "2014-02-02"=>55.72, 

  [...]

  "2014-03-25"=>172.24
}

# group by week
p Hash[ hash.map { |h, v| [Date.parse(h), v] } ]
    .group_by { |h, v| h.cweek }
    .values
    .map { |v| v.sum { |v| v.last } }
    .map { |v| v.round(2) }

#=> [283.68, 542.86, 1387.18, 855.67, 1057.0, 1846.94, 2621.45, 1085.45, 172.24]

# group by month
p Hash[ hash.map { |h, v| [Date.parse(h), v] } ]
    .group_by { |h, v| h.month }
    .values
    .map { |v| v.sum { |v| v.last } }
    .map { |v| v.round(2) }

#=> [200.1, 3786.99, 5865.38]

经过一些重构:

# group by week
p hash
    .group_by { |h, _| Date.parse(h).cweek }
    .map { |_, v| v.sum { |v| v.last }.round(2) }

# group by month
p hash
    .group_by { |h, _| Date.parse(h).month }
    .map { |_, v| v.sum { |v| v.last }.round(2) }

如果您对我使用下划线的原因感到好奇:http://po-ru.com/diary/rubys-magic-underscore/

答案 1 :(得分:0)

试试:

start_date = hash.min[0]
end_date = hash.max[0]
result = []
(start_date..end_date).each do |date|
  if date.wday == start_date.wday
    result << hash[date]
  else
    result[-1] += hash[date]
  end
end

或只是为了好玩:

(h.min[0]..h.max[0]).each {|d| (d.wday == h.min[0].wday && r << h[d])||(r[-1]+=h[d])}