How to combine overlapping time ranges (time ranges union)

后端 未结 10 1395
渐次进展
渐次进展 2020-12-08 05:19

I have an array with several time ranges inside:

[Tue, 24 May 2011 08:00:00 CEST +02:00..Tue, 24 May 2011 13:00:00 CEST +02:00,
 Tue, 24 May 2011 16:30:00 CE         


        
10条回答
  •  悲哀的现实
    2020-12-08 05:47

    I made a minor update to the answer from Wayne Conrad to handle edge cases involved with open-ended arrays (created with ... operator instead of .. operator).

    I changed the name to merge_continuous_ranges since while ranges like 0...1 and 1..2 do not overlap, their combined ranges are continuous, so it makes sense to combine them:

    def merge_continuous_ranges(ranges)
      ranges.sort_by(&:begin).inject([]) do |result, range|
        if !result.empty? && ranges_continuous?(result.last, range)
          result[0...-1] + [merge_ranges(result.last, range)]
        else
          result + [range]
        end
      end
    end
    
    def ranges_continuous?(a, b)
      a.include?(b.begin) || b.include?(a.begin) || a.end == b.begin || b.end == a.begin
    end
    
    def merge_ranges(a, b)
      range_begin = [a.begin, b.begin].min
      range_end = [a.end, b.end].max
    
      exclude_end = case a.end <=> b.end
      when -1
        b.exclude_end?
      when 0
        a.exclude_end? && b.exclude_end?
      when 1
        a.exclude_end?
      end
    
      exclude_end ? range_begin...range_end : range_begin..range_end
    end
    

提交回复
热议问题