2

我有一些图表的一些数据,这些图表排列在一个数组数组中,如下所示:

[[date1, value1], [date2, value2], [date3, value3]]
i.e. [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11]]

我的问题是我的绘图实用程序没有为“6-02-13”绘制任何数据,而我希望它绘制 0。

我有另一个包含所有有效日期的数组,例如["6-01-13", "6-02-13", "6-03-13", ...]

[date, 0]将我的数据数组中尚未存在的所有日期插入我的数据数组的最佳方法是什么?我不在乎数组的顺序。

我想我会按照以下方式做一些事情:

dates_array.each do |date|
  unless data_array.has_date(date)
    data_array.push([date, 0])
  end
end

但是如果不循环遍历所有日期并检查该日期是否在我的数据数组中表示,我想不出这个 has_date(date) 方法应该如何工作(这将是一个循环,因此并不理想)。

编辑:现有数据(和日期)作为数组从数据库中提取。

4

7 回答 7

5

将您的数组数组转换为默认值为零的散列:

def data_to_hash(data)
  Hash.new(0).merge(Hash[data])
end

data = [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11]]

hashed_data = data_to_hash(data)
p hashed_data['6-02-13']
p hashed_data['6-01-13']

输出:

0
5

任何不在数组中的日期都将返回 0。在大型数据集上使用散列作为数据结构比遍历数组查找日期要快得多。

答案更新

为了使无效键“粘”到散列,可以使用 Hash#new 的块变体:

def data_to_hash(data)
  Hash.new { |h,k| h[k] = 0 }.merge(Hash[data])
end

data = [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11]]
hashed_data = data_to_hash(data)

p hashed_data
%w{6-03-13 7-8-99}.each do |d|
  p hashed_data[d]
end
p hashed_data

输出:

{"6-01-13"=>5, "6-03-13"=>2, "6-04-13"=>11}
2
0
{"6-01-13"=>5, "6-03-13"=>2, "6-04-13"=>11, "7-8-99"=>0}

在此示例中,原始数据集中不存在 7-8-99,但在访问该键时设置为 0。

于 2013-06-07T20:34:54.937 回答
1
dates_array.each do |date|
  data.push [date, 0] unless data.map(&:first).include? date
end 

这行得通。也许有人可以改进它。

于 2013-06-07T20:36:29.460 回答
1

如果您知道日期范围,则可以使用该范围内的所有日期预先填充一个数组,并为它们提供一个默认值为零。 array = Array.new(31) {['date', 0]}

只需提供实际信息而不是日期。

或者这样做:(date..date+31).to_a.map!(&:to_s).zip([0]*32)

如果您向我提供获取现有日期项目的方式,我想我会制作更适合您的东西。

于 2013-06-07T20:38:26.373 回答
1

An alternative without using looping

dates_present = data.map(&:first)
dates_missing = dates_array - dates_present
data += dates_missing.map { |date| [date, 0] }
于 2017-08-25T22:29:48.483 回答
0

您可以使用以下策略:

dates_array = [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11]]
dates_array.push(["16-03-13",0]) unless dates_array.find{|i,j| i == "16-03-13"}
dates_array # => [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11], ["16-03-13", 0]]

这是完整的方法:

def date_check(arr,date)
  arr.push(["16-03-13",0]) unless arr.find{|i,j| i == date}
end

dates_array = [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11]]
date_check(dates_array,"16-03-13") # => [["6-01-13", 5], ["6-03-13", 2], ["6-04-13", 11], ["16-03-13", 0]]
date_check(dates_array,"6-01-13") # => nil
于 2013-06-07T20:47:31.643 回答
0

确保从数据库中对数据进行排序,或者dates_array.sort!{|a,b| Date.parse(a[0]) <=> Date.parse(b[0])}

(Date.parse(dates_array.first[0])..Date.parse(dates_array.last[0])).collect do |date|
  dates_array.find{|i| i[0] == date} || [date, 0]
end 

我不喜欢接受的答案 b/c 它需要一个现有的数组。

于 2013-06-07T22:54:33.620 回答
0
于 2013-06-07T23:39:10.707 回答