我会去:
d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,'%Y%m').mon ] }
=> ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan","Dec"]
要么:
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ m[/dd$/ ].to_i ] }
这可能会快一点.
问题是年界.您必须跟踪年份和月份,而不仅仅是月份,否则在使用uniq删除日期时,您将删除所有重复的月份索引.我使用YYYYMM格式,以获得正确的粒度.
编辑:
让它变得更有趣.
我有一些代码味道一直困扰着我.我不喜欢使用Date.strftime和Date.strptime,所以我又针对这个问题进行了另一次运行:这里有两个运行速度更快的解决方案,以及基准测试:
输出看起来像:
有趣. “人民币”现在正在落后.从测试中拉出它并使环圈100x上升:
这使:
这基本上是两种新方式之间的关系.作为肛门,我会选择mb2,因为如果我这样做数百万次会更快一些,但你的里程可能会有所不同.
require 'benchmark'
require 'date'
d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
n = 100
Benchmark.bm(8) do |x|
x.report('strptime') { n.times { (d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,'%Y%m').mon ] } } }
x.report('regex') { n.times { (d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ m[/dd$/ ].to_i ] } } }
end
user system total real
strptime 3.d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]
d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]0 0.020000 3.080000 ( 3.076614)
regex 2.820000 0.010000 2.830000 ( 2.829366)
require 'benchmark'
require 'date'
def regex_months_between(d1,d2)
d1,d2 = [d1,d2].map{ |d| Date.parse(d) }.minmax
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ m[/dd$/ ].to_i ] }
end
def months_between1(d1,d2].map{ |d| Date.parse(d) }.minmax
months = (d2.mon - d1.mon) + (d2.year - d1.year) * 12
month_names = []
months.times{ |m|
month_names << Date::ABBR_MONTHNAMES[(d1 >> m).mon]
}
month_names << Date::ABBR_MONTHNAMES[d2.mon]
month_names
end
def months_between2(d1,d2].map{ |d| Date.parse(d) }.minmax
months = (d2.mon - d1.mon) + (d2.year - d1.year) * 12
(d1.mon ... (d1.mon + months)).each_with_object(Date::ABBR_MONTHNAMES[d1.mon,1]) { |month_offset,month_names_array|
month_names_array << Date::ABBR_MONTHNAMES[(d1 >> month_offset).mon]
}
end
puts regex_months_between('jan 1 2011','dec 31 2012').join(',')
puts months_between1('jan 1 2011',')
puts months_between2('jan 1 2011',')
n = 100
Benchmark.bm(3) do |b|
b.report('rmb') { n.times { regex_months_between('jan 1 2011','dec 31 2012') } }
b.report('mb1') { n.times { months_between1('jan 1 2011','dec 31 2012') } }
b.report('mb2') { n.times { months_between2('jan 1 2011','dec 31 2012') } }
endJan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,Jan,Dec
Jan,Dec
user system total real
rmb 2.810000 0.010000 2.820000 ( 2.820732)
mb1 0.d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]
0 0.000000 0.
d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]
0 ( 0.057763)
mb2 0.
d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]0 ( 0.057112)
n = 10_000
Benchmark.bm(3) do |b|
b.report('mb1') { n.times { months_between1('jan 1 2011','dec 31 2012') } }
enduser system total real
mb1 5.570000 0.d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')
(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m,"Dec"]0 5.630000 ( 5.615789)
mb2 5.570000 0.040000 5.610000 ( 5.611323)