这基本上是我需要做的,但我不使用表,所以我需要在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
如果我希望用户能够选择按小时,天,周等查看数据。这是最佳策略吗?
答案 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}]