Ruby: intersection between two ranges Ruby: intersection between two ranges ruby ruby

Ruby: intersection between two ranges


require 'date'class Range  def intersection(other)    return nil if (self.max < other.begin or other.max < self.begin)     [self.begin, other.begin].max..[self.max, other.max].min  end  alias_method :&, :intersectionendp (Date.new(2011,1,1)..Date.new(2011,1,15)) & (Date.new(2011,1,10)..Date.new(2011,2,15))#<Date: 2011-01-10 ((2455572j,0s,0n),+0s,2299161j)>..#<Date: 2011-01-15 ((2455577j,0s,0n),+0s,2299161j)>


You can try this to get a range representing intersection

range1 = Date.new(2011,12,1)..Date.new(2011,12,10)range2 = Date.new(2011,12,4)..Date.new(2011,12,12)inters = range1.to_a & range2.to_aintersected_range = inters.min..inters.max

Converting your example:

class Range    def intersection(other)      raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)      inters = self.to_a & other.to_a    inters.empty? ? nil : inters.min..inters.max   end    alias_method :&, :intersection  end


I baked this solution for ascending ranges, also taking care of the exclude end situations:

intersect_ranges = ->(r1, r2) do  new_end = [r1.end, r2.end].min  new_begin = [r1.begin, r2.begin].max  exclude_end = (r2.exclude_end? && new_end == r2.end) || (r1.exclude_end? && new_end == r1.end)  valid = (new_begin <= new_end && !exclude_end)   valid ||= (new_begin < new_end && exclude_end))  valid ? Range.new(new_begin, new_end, exclude_end) : nilend

I'm also a bit worried by you guys adding it to the Range class itself, since the behavior of intersecting ranges is not uniformly defined. (How about intersecting 1...4 and 4...1? Why nil when there is no intersection; we could also say this is an empty range: 1...1 )