通过时间戳将项目组合到间隔箱中

时间:2015-06-16 15:53:43

标签: javascript ruby-on-rails ruby

这基本上是我需要做的,但我不使用表,所以我需要在Ruby / Rails甚至Javascript中完成。数据是从一个有点慢的外部调用返回的,所以我试图尽快格式化数据。可能有多达数千个元素。

我得到了这个输入:

{"data": [
            {"time": "2015-04-01 05:10","count": 1},
            {"time": "2015-04-01 06:00","count": 3},
            {"time": "2015-04-01 06:50","count": 2},
            {"time": "2015-04-01 07:40","count": 8},
            {"time": "2015-04-01 07:48","count": 5}
        ]
}

想要返回这样的东西(1小时桶):

{"buckets": [
              {"time": "2015-04-01 05:00", "count": 1},
              {"time": "2015-04-01 06:00", "count": 5},
              {"time": "2015-04-01 07:00", "count": 13}
            ]
}

我唯一能想到的就是使用一堆if并迭代添加计数如果小时=== last.hour else创建一个新元素,如果它不同。感觉就像必须有一个更优雅的解决方案。

我似乎无法在Ruby / Javascript中找到一个很好的解决方案。这是相同的想法,但这不在我的数据库中。 Grouping into interval of 5 minutes within a time range

如果我希望用户能够选择按小时,天,周等查看数据。这是最佳策略吗?

2 个答案:

答案 0 :(得分:1)

将时间缩短到小时,并使用聚合计数构建新哈希。如果您希望用户选择时间段,只需根据存储桶大小选择strftime格式。您可以对Time对象进行数学运算,但无论如何您都要对其进行格式化,所以也可以在那里进行。由于您在Rails中,您还可以使用Time#beginning_of_*方法。

如果您的数据位于data.json,则会出现一个脚本:

require 'json'
require 'time'

data = JSON.parse(File.read('data.json'))['data']

result = Hash.new(0) # Missing entries get initialized to 0

data.each do |entry|
  time = Time.parse(entry['time'])
  hour = time.strftime('%Y-%m-%d %H:00') # Effectively round to the hour
  result[hour] += entry['count']
end

result_list = result.map do |time, count|
  {time: time, count: count}
end
puts JSON.pretty_generate(buckets: result_list)

输出:

$ ruby group.rb
{
  "buckets": [
    { "time": "2015-04-01 05:00", "count": 1 },
    { "time": "2015-04-01 06:00", "count": 5 },
    { "time": "2015-04-01 07:00", "count": 13 }
  ]
}

答案 1 :(得分:1)

在使用beginning_of_hour的Rails中,您可以将这些时间组合在一起:

a = [
     {"time"=>"2015-04-01 05:10","count"=>1},
     {"time"=>"2015-04-01 06:00","count"=>3},
     {"time"=>"2015-04-01 06:50","count"=>2},
     {"time"=>"2015-04-01 07:40","count"=>8},        
     {"time"=>"2015-04-01 07:48","count"=>5}                     
    ] 

hash = Hash.new(0)
a.each{ |k|
  hash[k["time"].to_time.beginning_of_hour] += k["count"]
}

hash.map{|k,v| {"time" => k, "count" => v}}
# => [{"time"=>2015-04-01 05:00:00 UTC, "count"=>1}, {"time"=>2015-04-01 06:00:00 UTC, "count"=>5}, {"time"=>2015-04-01 07:00:00 UTC, "count"=>13}]