2016-03-02 189 views
0

如何在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

回答

2
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 
0
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

2
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