我有这段代码:
date_counter = Time.mktime(2011,01,00,"+05:00") @weeks = Array.new (date_counter..Time.now).step(1.week) do |week| logger.debug "WEEK: " + week.inspect @weeks << week end
Sat Jan 01 00:00:00 -0500 2011 Sat Jan 08 00:00:00 -0500 2011 Sat Jan 15 00:00:00 -0500 2011 etc.
但执行时间完全是垃圾!每周计算大约需要4秒钟.
我在这段代码中遗漏了一些奇怪的低效率吗?看起来很简单.
我正在使用Rails 3.0.3运行Ruby 1.8.7.
解决方法
假设MRI和Rubinius使用类似的方法生成范围,所有无关检查使用的基本算法和一些Fixnum优化等被删除是:
class Range def each(&block) current = @first while current < @last yield current current = current.succ end end def step(step_size,&block) counter = 0 each do |o| yield o if counter % step_size = 0 counter += 1 end end end
对于Time对象,#succ会在一秒后返回时间.因此,即使你每周都要求它,但无论如何它必须在两次之间逐步完成.
编辑:解决方案
构建一系列Fixnum,因为它们具有优化的Range#step实现.
就像是:
date_counter = Time.mktime(2011,"+05:00") @weeks = Array.new (date_counter.to_i..Time.now.to_i).step(1.week).map do |time| Time.at(time) end.each do |week| logger.debug "WEEK: " + week.inspect @weeks << week end