2个范围集之间的交集

问题描述:

如何在ruby中做范围拦截?2个范围集之间的交集

像这样:

[-4, 3] intersection [-2, 5] = [-2, 3] 
[10, 20] intersection [5, 10] = [10] 
[-10, -5] intersection [-8, -3] = [-8,-5] 
[-5, -3] intersection [2, 20] = nil 
+1

'[-4,3]'是*数组*,A *范围*看起来像这样:'(-4..3)' – Stefan

+0

而一个['Set'](http://ruby-doc.org/stdlib-2.3.0/libdoc/set/rdoc/Set.html)是别的。 – Stefan

+0

而表达式是非法的。 – sawa

def foo((a, b), (c, d)) 
    min, max = [a, c].max, [b, d].min 
    case min <=> max 
    when -1 then [min, max] 
    when 0 then [min] 
    when 1 then nil 
    end 
end 

foo([-4, 3], [-2, 5]) # => [-2, 3] 
foo([10, 20], [5, 10]) # => [10] 
foo([-10, -5], [-8, -3]) # => [-8, -5] 
foo([-5, -3], [2, 20]) # => nil 

f = [-4, 3] 
s = [-2, 5] 
inter = [[f[0],s[0]].max, [f[1],s[2]].min].uniq 
inter = nil if inter[1] && inter[1] < inter[0] 
+0

或者,'inter = nil,除非inter.sort == inter'。 – sawa

class Range 
    def range_overlap(other) 
    [self.min, other.min].max..[self.max, other.max].min 
    end 
end 

(-4..3 ).range_overlap -2..5 #=> -2..3 
(10..20).range_overlap 5..10 #=> 10..10 
(-10..-5).range_overlap -8..-3 #=> -8..-5 
(-5..-3).range_overlap -2..20 #=> -2..-3 
(1..4 ).range_overlap 2..3 #=> 2..3 

r.first > r.last,如在r = -2..-3,表示不存在重叠。如果你喜欢nil在这种情况下,要返回,使用

r = ([self.min, other.min].max)..([self.max, other.max].min) 
r.last >= r.first ? r : nil 

我也回到[10,10]而不是说,10(当然不是[10]),因为我相信这会令你的后面的代码更易于编写。 (这是类似于返回[[1,2], [3], [4,5]],而不是[[1,2], 3, [4,5]]的方法。)

我认为它很可能是最好的总是返回Range对象。允许后续的将被写入代码,例如:

r = range_overlap(other) 
case r.first <=> r.last 
    when 1 # r.first > r.last 
    <put out the trash> 
    when 0 # r.first == r.last 
    <let the cat out> 
    else # r.first < r.last 
    <go to a movie> 
end