图表与空月

时间:2017-08-05 09:11:47

标签: ruby-on-rails ruby hash charts

我有一个哈希

{"Apr 2016"=>6.0, "Aug 2016"=>7.5, "Jan 2017"=>8.666666666666666, "Apr 2017"=>7.333333333333333, "May 2017"=>7.571428571428571, "Jun 2017"=>6.75, "Jul 2017"=>6.7272727272727275}

我希望显示一个图表行,但我的哈希中的空白月会创建丑陋的图表, 我会知道如何获得空的月份,并给予以前的值有价值来获得类似

的东西
{"Apr 2016"=>6.0, "May 2016"=>6, "June 2016"=>6, "July 2016"=>6 "Aug 2016"=>7.5, "Jan 2017"=>8.666666666666666...}

更新:我得到所有的值,但我不知道当值为空时如何分配前一个值,我尝试了很多东西,但没有任何工作

2 个答案:

答案 0 :(得分:1)

<强>代码

require 'date'

def fill_in(h)
  month, date_last = h.keys.map { |s| Date.strptime(s, '%b %Y') }.minmax
  h_out = {}
  last = nil
  loop do
    str = month.strftime('%b %Y')
    h_out[str] = h.fetch(str, last)
    last = h_out[str]
    return h_out if month == date_last
    month = month >> 1
  end
end

示例

h = { "May 2016"=>6.0, "Aug 2016"=>7.5, "Jan 2017"=>8.6, "Nov 2016"=>7.3 }
fill_in(h)
  #=> {"May 2016"=>6.0, "Jun 2016"=>6.0, "Jul 2016"=>6.0,
  #    "Aug 2016"=>7.5, "Sep 2016"=>7.5, "Oct 2016"=>7.5,
  #    "Nov 2016"=>7.3, "Dec 2016"=>7.3, "Jan 2017"=>8.6}

<强>解释

请参阅Date::strptimeDate#strftimeDate#>>Enumerable#minmaxHash#fetch

我们来看看示例中给出的h的步骤。

month, date_last = h.keys.map { |s| Date.strptime(s, '%b %Y') }.minmax
  #=> [#<Date: 2016-05-01 ((2457510j,0s,0n),+0s,2299161j)>,
  #    #<Date: 2017-01-01 ((2457755j,0s,0n),+0s,2299161j)>]
month
  #=> #<Date: 2016-05-01 ((2457510j,0s,0n),+0s,2299161j)>
date_last
  #=> #<Date: 2017-01-01 ((2457755j,0s,0n),+0s,2299161j)>
h_out = {}
last = nil

执行一次循环计算

str = month.strftime('%b %Y')
  #=> #<Date: 2016-05-01 ((2457510j,0s,0n),+0s,2299161j)>.strftime('%b %Y')
  #=> "May 2016"
h_out[str] = h.fetch("May 2016", nil)
  #=> h.fetch(str, last)
  #=> 6.0
last = h_out[str]
  #=> 6.0
return h_out if month == date_last
  # <do not return>
month = month >> 1
  #=> #<Date: 2016-06-01 ((2457541j,0s,0n),+0s,2299161j)>

现在再次进行循环。

str = month.strftime('%b %Y')
  #=> "Jun 2016"
h_out[str] = h.fetch(str, last)
  #=> 6.0

此时fetch使用默认值last #=> 6.0),因为h没有键"Jun 2016"

last = h_out[str]
  #=> 6.0
return h_out if month == date_last
  # <do not return>
month = month >> 1
  #=> #<Date: 2016-07-01 ((2457571j,0s,0n),+0s,2299161j)>

其余的计算方法类似。

答案 1 :(得分:0)

请阅读更新。

您需要填补空白:

require 'date'
data = {'Apr 2016' => 6.0, 'Aug 2016' => 7.5, 'Jan 2017' => 8.666666666666666, 'Apr 2017' => 7.333333333333333, 'May 2017' => 7.571428571428571, 'Jun 2017' => 6.75, 'Jul 2017' => 6.7272727272727275}
range = Date.parse('1.4.2016')..Date.parse('1.7.2017')

range.each do |date|
  key = date.strftime('%b %Y')
  data[key] ||= 0
end

这会创建一个包含开始日期和结束日期的日期范围,然后对其进行迭代。它从日期(strftime)创建一个String,并检查它是否已经在哈希值(||=)中,如果没有,则将值设置为0 根据您呈现图表的方式以及实际显示的内容,0可能是错误的值,您可能需要将其设置为nil

更新: 我刚刚意识到这不是最有效的方法,因为范围将包含每天的条目,而不是每月。我将代码保留在答案中,但您应该使用类似的内容:

require 'date'
data = {'Apr 2016' => 6.0, 'Aug 2016' => 7.5, 'Jan 2017' => 8.666666666666666, 'Apr 2017' => 7.333333333333333, 'May 2017' => 7.571428571428571, 'Jun 2017' => 6.75, 'Jul 2017' => 6.7272727272727275}

current = Date.parse('1.4.2016')
stop = Date.parse('1.7.2017')

while current <= stop do
  key = current.strftime('%b %Y')
  data[key] ||= 0
  current = current >> 1
end