Gla*_*eep 2 ruby optimization performance rake ruby-on-rails
我有一个300K字符串的数组,代表日期:
date_array = [
"2007-03-25 14:24:29",
"2007-03-25 14:27:00",
...
]
Run Code Online (Sandbox Code Playgroud)
我需要计算此数组中每个日期的出现次数(例如,"2011-03-25"的所有日期字符串).确切的时间无关紧要 - 只是日期.我知道文件中的日期范围.所以我有:
Date.parse('2007-03-23').upto Date.parse('2011-10-06') do |date_to_count|
count = 0
date_array.each do |date_string|
if Date.parse(date_string) >= date_to_count &&
Date.parse(date_string) <= date_to_count
count += 1
end
end
puts "#{date_to_count} occurred #{count} times."
end
Run Code Online (Sandbox Code Playgroud)
在我的机器上计算仅一个日期的出现时间超过60秒.我可以通过哪些方式优化此任务的性能?
可能有用的注释:我使用的是Ruby 1.9.2.此脚本使用rake 0.9.2在Rake任务中运行.它date_array是从CSV文件加载的.在每次迭代中,它count都保存为我的Rails项目数据库中的记录.
是的,如果日期格式相同,则根本不需要解析日期.了解您的数据是您可以拥有的最强大的工具之一.
如果日期时间字符串都是相同的格式(yyyy-mm-dd HH:MM:SS)那么你可以做类似的事情
data_array.group_by{|datetime| datetime[0..9]}
Run Code Online (Sandbox Code Playgroud)
这将为您提供一个哈希,比如日期字符串作为键,日期数组作为值
{
"2007-05-06" => [...],
"2007-05-07" => [...],
...
}
Run Code Online (Sandbox Code Playgroud)
所以你必须得到每个数组的长度
data_array.group_by{|datetime| datatime[0..9]}.each do |date_string, date_array|
puts "#{date_string} occurred #{date_array.length} times."
end
Run Code Online (Sandbox Code Playgroud)
当然,当您不需要时,该方法会通过日期数组浪费内存.
怎么样
一种更节省内存的方法
date_counts = {}
date_array.each do |date_string|
date = date_string[0..9]
date_counts[date] ||= 0 # initialize count if necessary
date_counts[date] += 1
end
Run Code Online (Sandbox Code Playgroud)
最终会得到一个哈希,其中日期字符串为键,计数为值
{
"2007-05-06" => 123,
"2007-05-07" => 456,
...
}
Run Code Online (Sandbox Code Playgroud)
将所有东西放在一起
date_counts = {}
date_array.each do |date_string|
date = date_string[0..9]
date_counts[date] ||= 0 # initialize count if necessary
date_counts[date] += 1
end
Date.parse('2007-03-23').upto Date.parse('2011-10-06') do |date_to_count|
puts "#{date_to_count} occurred #{date_counts[date_to_count.to_s].to_i} times."
end
Run Code Online (Sandbox Code Playgroud)