当存在空条目时,如何在数组中添加值?

时间:2010-12-27 06:45:04

标签: ruby-on-rails ruby arrays statistics time-series

我想创建一个真正的时间序列数组。目前,我使用统计信息宝石来提取每个'日'的值:

define_statistic :sent_count, :count
=> :all, :group => 'DATE(date_sent)',    
:filter_on => {:email_id => 'email_id
> = ?'}, :order => 'DATE(date_sent) ASC'

这样做是创建一个有日期值的数组,例如

[["12-20-2010",1], ["12-24-2010",3]]

但是我需要它来填充空值,所以看起来更像是:

[["12-20-2010",1], ["12-21-2010",0], ["12-22-2010",0], ["12-23-2010",0], ["12-24-2010",3]]

注意第二个示例如何为第一个数组中缺少的天数设置“0”。

2 个答案:

答案 0 :(得分:5)

#!/usr/bin/ruby1.8

require 'date'
require 'pp'

def add_missing_dates(series)
  series.map do |date, value|
    [Date.strptime(date, '%m-%d-%Y'), value]
  end.inject([]) do |series, date_and_value|
    filler = if series.empty?
               []
             else
               ((series.last[0]+ 1)..(date_and_value[0] - 1)).map do |date|
                 [date, 0]
               end
             end
    series + filler + [date_and_value]
  end.map do |date, value|
    [date.to_s, value]
  end
end

a = [["12-20-2010",1], ["12-24-2010",3]]
pp add_missing_dates(a)
# => [["2010-12-20", 1],
# =>  ["2010-12-21", 0],
# =>  ["2010-12-22", 0],
# =>  ["2010-12-23", 0],
# =>  ["2010-12-24", 3]]

我建议不要使用猴子修补基类来包含这种方法:这不是全部目的;即使它是,它只是不需要在那里。我会把它放在一个模块中,你可以将它混合到任何需要的代码中:

module AddMissingDates
  def add_missing_dates(series)
    ...
  end
end

class MyClass
  include AddMissingDates
  ...
end

但是,如果你真的想:

def Array.add_missing_dates(series)
  ...
end

答案 1 :(得分:0)

这有效:

#!/usr/bin/env ruby

require 'pp'
require 'date'

# convert the MM-DD-YYYY format date string to a Date
DATE_FORMAT = '%m-%d-%Y'
def parse_date(s)
  Date.strptime(s, DATE_FORMAT)
end

dates = [["12-20-2010",1], ["12-24-2010",3]]

# build a hash of the known dates so we can skip the ones that already exist.
date_hash = Hash[*dates.map{ |i| [parse_date(i[0]), i[-1]] }.flatten]

start_date_range = parse_date(dates[0].first) 
end_date_range   = parse_date(dates[-1].first)

# loop over the date range...
start_date_range.upto(end_date_range) do |d|
  # ...and adding entries for the missing ones.
  date_hash[d] = 0 if (!date_hash.has_key?(d))
end

# convert the hash back into an array with all dates
all_dates = date_hash.keys.sort.map{ |d| [d.strftime(DATE_FORMAT), date_hash[d] ] }
pp all_dates

# >> [["12-20-2010", 1],
# >>  ["12-21-2010", 0],
# >>  ["12-22-2010", 0],
# >>  ["12-23-2010", 0],
# >>  ["12-24-2010", 3]]

大多数代码都在准备,要么构建一个新数组,要么将日期对象返回给字符串。