2011-09-27 64 views
3

我有查询(对于MongoDB数据库),它返回的对象已被映射减少,对象每15分钟报告一次,但问题是,如果说我们有一个严重错误其中一段时间​​的服务器将被下载。红宝石,数组时间的差距

拿这个阵列为例:

[ 
    {:timestamp=>2011-09-26 19:00:00 UTC, :count=>318}, 
    {:timestamp=>2011-09-26 19:15:00 UTC, :count=>308}, 
    {:timestamp=>2011-09-26 19:30:00 UTC, :count=>222}, 
    {:timestamp=>2011-09-26 19:45:00 UTC, :count=>215}, 
    {:timestamp=>2011-09-26 20:00:00 UTC, :count=>166}, 
    {:timestamp=>2011-09-26 21:15:00 UTC, :count=>149}, 
    {:timestamp=>2011-09-26 21:30:00 UTC, :count=>145}, 
    {:timestamp=>2011-09-26 21:45:00 UTC, :count=>107}, 
    {:timestamp=>2011-09-26 22:00:00 UTC, :count=>137}, 
    {:timestamp=>2011-09-26 22:15:00 UTC, :count=>135}, 
    {:timestamp=>2011-09-26 22:30:00 UTC, :count=>191}, 
    {:timestamp=>2011-09-26 22:45:00 UTC, :count=>235} 
] 

你会发现,时间是缺少时间范围:

{:timestamp=>2011-09-26 20:15:00 UTC}, 
{:timestamp=>2011-09-26 20:30:00 UTC}, 
{:timestamp=>2011-09-26 20:45:00 UTC}, 
{:timestamp=>2011-09-26 21:00:00 UTC} 

我怎样才能把顶部为输入和演绎那些将是缺失的行?时间增量总是15分钟,其实际上是一个真正的日期对象而不是像这样的字符串。

我只是无法想象如何迭代这个。

任何帮助将不胜感激。

回答

3

我能想到的最简单方法是为了通过时间戳的数组,然后像做了以下内容:

missing_times = [] 
reports.each_with_index do |report, index| 
    if reports[index + 1] 
    if report.timestamp.advance(minutes: 15) < report[index + 1].timestamp 
     i = 0 
     while(report.timestamp.advance(minutes: 15*i) < report[index+1].timestamp) 
     missing_times << report.timestamp.advance(minutes: 15*i) 
     end 
    end 
    end 
end 

我以前写类似的代码,找出了一系列半小时的差距的预约

虽然看起来我的解决方案可能会在reports.first和reports.last之间以15分钟的增量循环多次,但实际上它只会在所有可用的增量之间循环一次,报告之间的报告.first和reports.last

+0

我在执行此操作时遇到了一些麻烦,如果报告[:timestamp] .advance(分钟:15)

0

只需从第一个时间戳开始,然后增加15分钟,验证该条目是否存在,并继续前进,直到达到最后一个时间戳。

1

如果您以15分钟的增量创建总时间范围的数组,并且仅比较您的报告集并删除所有匹配项,则不是在循环内执行多个循环,而是使用大型数据集更高效。

start_time = report.first 
span = ((report.last - start_time)/60/15).to_i # this gives the number of 15min blocks 
test_array = [] 
span.times do |i| 
    test_array << start_time + i*15.minutes 
end 
report.each do |r| 
    test_array.delete(r) # or in your case, r.timestamp 
end 

我认为它的工作原理,但也想不出一个好办法,使时间戳的参考表,所以我砍死了有我的方式。

+1

我的答案只在间隙大于15分钟时循环,如果没有间隙,我的解决方案只在数组上迭代一次。另外,我的数组不会循环所有可能的时间,只有那些填补空白。您的解决方案将始终有2个循环,一个负载时间跨度,另一个循环遍历所有元素。当没有差距时,您的解决方案将在所有元素上循环两次。我最糟糕的情况将总是在所有可用增量上循环一次,等于你的'span.times'循环 –

+0

此外,test_array.delete迭代数组本身以找到要删除的元素,请参阅代码:http:// www。 ruby-doc.org/core/classes/Array.src/M000255.html,所以你的代码是O(n^2),因为每次你调用delete,你都可能遍历整个数组 –

+0

你是对的 - 谢谢为此解释。 :) – joseph