假设我在Ruby中有以下日期范围:
2011年1月1日星期六。2011年2月1日星期二
2011年1月5日星期三.Thu,2011年2月17日
2011年2月2日星期三。2011年3月1日星期二
Sun,2012年1月1日.Thu,2012年1月5日
我可以通过什么程序获取所有这四个范围并获得输出,告诉我2011年3月2日星期三范围内有中断?
修改 塞尔吉奥是对的,似乎没有任何内置。我可以这样理解:
x = Range.new(Date.parse('2011-01-01'), Date.parse('2011-02-01'))
r = Range.new(Date.parse('2011-01-05'), Date.parse('2011-02-17'))
y = Range.new(Date.parse('2011-02-02'), Date.parse('2011-03-01'))
z = Range.new(Date.parse('2012-01-01'), Date.parse('2012-01-05'))
ranges = [x,y,z,r]
dates = ranges.collect!{|r|r.to_a}.flatten!.uniq!.sort!
dates.delete_if do |date|
index = ranges.index(date)
next_date = ranges[index + 1]
next_date == date + 1 || next_date.nil?
end
仍在寻找最佳解决方案。
答案 0 :(得分:2)
Ruby的Enumerable.chunk
在这里很有用。为简单起见,我缩短了检查范围,并添加了一个无序的附加范围,以表明它处理的是无序范围:
require 'date'
date_ranges = [
'01 Jan 2011', '03 Jan 2011',
'02 Jan 2011', '04 Jan 2011',
'02 Mar 2011', '03 Mar 2011',
'01 Jan 2000', '02 Jan 2000'
].each_slice(2).map{ |dates|
Range.new(
*dates.map{ |d|
Date.parse(d)
}
)
}
gaps = date_ranges
.inject([]){ |a, d| a |= d.to_a } # accumulate the unique dates in the ranges
.sort # sort to get them in ascending order
.each_with_index # add an offset into the order
.chunk{ |d,i| d - i } # group by the delta
.to_a[1 .. -1] # grab all but the first group
.map{ |g,dates| dates.first.first } # strip off the groups and indexes
puts gaps
输出:
2011-01-01
2011-03-02
因为我添加了无序范围,所以原始起始范围现在是一个差距,就像2011年3月2日的日期一样。
这将为您提供chunk
正在做的事情的示例:
[1,2,3,4,5].each_with_index.chunk{ |n,i| n-i }.to_a # => [[1, [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4]]]]
[1,2, 4,5].each_with_index.chunk{ |n,i| n-i }.to_a # => [[1, [[1, 0], [2, 1]]], [2, [[4, 2], [5, 3]]]]
答案 1 :(得分:1)
数组算术:
date_ranges = [
'01 Jan 2011', '03 Jan 2011',
'02 Jan 2011', '04 Jan 2011',
'02 Mar 2011', '03 Mar 2011',
'01 Jan 2000', '02 Jan 2000'
].each_slice(2).map{ |dates|
Range.new(
*dates.map{ |d|
Date.parse(d)
}
)
}
dates = date_ranges.collect{|r| r.to_a}.flatten
((dates.min..dates.max).to_a - dates).min
答案 2 :(得分:0)
我接近的方式就是这样(完成这个作为读者的exersize):
class DateRange
def initialize (start, end)
...
end
def interection (range)
# Determine the intersection of the current range and another
# Returns either nil or a new DateRange object.
...
end
def expand (range)
# Expand the current range to include the passed in range
...
end
end
class DateRangeSet
include Enumerable
def <<(range)
# Inspect the current ranges, and any that have an intersection, merge them
...
end
def each
@ranges.each { |r| yield r }
end
end
假设您的input
是[start,end]
数组的数组,例如:
coll = DateRangeCollection.new
input.each { |s, e| coll << DateRange.new(s,e) }
puts "Gaps found!" if coll.to_a.count > 1
有人说......也许有一种更简洁的方式?