我知道我能做到:
(1..30).cover?(2)
=> true
Run Code Online (Sandbox Code Playgroud)
但是当我尝试对另一个范围做同样的事情时,它总是返回false:
(1..30).cover?(2..3)
=> false
Run Code Online (Sandbox Code Playgroud)
所以我的问题是 - 有没有优雅的方法来比较红宝石中的两个范围?在我的情况下,我想检查两个DateTime范围是否重叠.提前致谢.
在给定范围A时,两个范围重叠:
例子:
Range A |-----|
|-----| Case 1
|-----| Case 2
|-| Case 1 + 2
|---------| Case 3
Run Code Online (Sandbox Code Playgroud)
仔细观察的规则是:当范围B在范围A结束之前开始且范围B在范围A开始之后结束时,两个范围重叠。
def ranges_overlap?(range_a, range_b)
range_b.begin <= range_a.end && range_a.begin <= range_b.end
end
Run Code Online (Sandbox Code Playgroud)
更新:该Range#cover?方法现在接受范围类型参数。当您使用的是Ruby版本时>= 2.6,以下各项可以立即使用:
(1..30).cover?(2..3)
#=> true
Run Code Online (Sandbox Code Playgroud)
def overlap?(r1,r2)
!(r1.first > r2.last || r1.last < r2.first)
end
overlap? 1..5, 4..10 #=> true
overlap? 1..5, 6..10 #=> false
overlap? 1..10, 4..8 #=> true
overlap? 1..4, 4..8 #=> true
Run Code Online (Sandbox Code Playgroud)
操作线相当于:
r1.first <= r2.last && r1.last >= r2.first
Run Code Online (Sandbox Code Playgroud)
我通常会尽量避免否定,但在这种情况下,我认为它更适合它.
其他方式:
def overlap?(r1,r2)
!(([r1.first, r2.first].min..[r1.last, r2.last].max).size >= r1.size + r2.size)
end
overlap? 1..5, 4..10 #=> true
overlap? 1..5, 6..10 #=> false
overlap? 1..10, 4..8 #=> true
overlap? 1..4, 4..8 #=> true
Run Code Online (Sandbox Code Playgroud)
操作线相当于:
([r1.first, r2.first].min..[r1.last, r2.last].max).size < r1.size + r2.size
Run Code Online (Sandbox Code Playgroud)
再一次,我更喜欢有否定的那个.
如果你想要 Rails 实现,你可以使用
class Range
def overlaps?(other)
cover?(other.first) || other.cover?(first)
end
end
Run Code Online (Sandbox Code Playgroud)
(1..5).overlaps?(4..6) # => true
(1..5).overlaps?(7..9) # => false
Run Code Online (Sandbox Code Playgroud)
Range#overlap?Ruby 3.3+ 中有
true如果范围相互重叠则返回,否则返回false
它适用于不同类型的范围:
(5..10).overlap?(10..20)
# => true
('a'..'e').overlap?('b'..'f')
# => true
Run Code Online (Sandbox Code Playgroud)
当开始 > 结束时返回false:
(5..1).overlap?(2..3)
# => false
Run Code Online (Sandbox Code Playgroud)
false当尝试检查不可比较的范围时它会返回:
(5..10).overlap?('a'..'e')
# => false
Run Code Online (Sandbox Code Playgroud)
它适用于独家范围:
(5..10).overlap?(1...5)
# => false
(1...5).overlap?(5..10)
# => false
Run Code Online (Sandbox Code Playgroud)
它适用于无限和无始的范围:
(1..).overlap?(..1)
# => true
(1..).overlap?(...1)
# => false
Run Code Online (Sandbox Code Playgroud)
当尝试传递非范围时会引发错误
(1..5).overlap?(1)
# raise TypeError (expected Range)
Run Code Online (Sandbox Code Playgroud)