How to combine overlapping time ranges (time ranges union)

后端 未结 10 1376
渐次进展
渐次进展 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:57

    Dont you just want to find the smallest first value and the largest last value from the set of arrays?

    ranges = [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 CEST +02:00..Tue, 24 May 2011 18:00:00 CEST +02:00,
     Tue, 24 May 2011 08:00:00 CEST +02:00..Tue, 24 May 2011 09:00:00 CEST +02:00,
     Tue, 24 May 2011 15:30:00 CEST +02:00..Tue, 24 May 2011 18:00:00 CEST +02:00]
    
    union = [ranges.collect(&:first).sort.first, ranges.collect(&:last).sort.last]
    
    0 讨论(0)
  • 2020-12-08 05:59

    The gem range_operators does a wonderful job by adding missing features to the Ruby Range class. It is way smaller than adding the whole facets gem.

    I your case the solution would be the rangify method, which is added to the Array class and would do exactly what you are looking for.

    0 讨论(0)
  • 2020-12-08 06:00

    Given a function that returns truthy if two ranges overlap:

    def ranges_overlap?(a, b)
      a.include?(b.begin) || b.include?(a.begin)
    end
    

    (this function courtesy of sepp2k and steenslag)

    and a function that merges two overlapping ranges:

    def merge_ranges(a, b)
      [a.begin, b.begin].min..[a.end, b.end].max
    end
    

    then this function, given an array of ranges, returns a new array with any overlapping ranges merged:

    def merge_overlapping_ranges(overlapping_ranges)
      overlapping_ranges.sort_by(&:begin).inject([]) do |ranges, range|
        if !ranges.empty? && ranges_overlap?(ranges.last, range)
          ranges[0...-1] + [merge_ranges(ranges.last, range)]
        else
          ranges + [range]
        end
      end
    end
    
    0 讨论(0)
  • 2020-12-08 06:00

    Some kind of algorithm that might help:

    Sort range array by start time (r1, r2, r3, r4, .. rn)
    
    for each range pair [r1, r2], [r2, r3] .. [rn-1, rn]:
        if r1_end > r2_start: # they overlap
            add [r1_start, r2_end] to new range array
        else: # they do not overlap
            add [r1] and [r2] to new range array (no changes)
    
    startover with the new range array until no more changes
    
    0 讨论(0)
提交回复
热议问题