我知道我能做到:
return render(request, ('core/add_regent.html', context_dict), {'form': form})
但是当我尝试对另一个范围做同样的事情时,它总是返回false:
(1..30).cover?(2)
=> true
所以我的问题是 - 有没有优雅的方法来比较红宝石中的两个范围?在我的情况下,我想检查两个DateTime范围是否重叠。提前谢谢。
答案 0 :(得分:7)
在以下情况下,给定范围A的两个范围重叠:
示例:
Range A |-----|
|-----| Case 1
|-----| Case 2
|-| Case 1 + 2
|---------| Case 3
仔细观察规则:当范围B在范围A结束之前开始范围B时,两个范围重叠,而范围B在范围A开始之后结束。
def ranges_overlap?(range_a, range_b)
range_b.begin <= range_a.end && range_a.begin <= range_b.end
end
更新: Range#cover?
方法现在接受范围类型参数。当您使用Ruby版本>= 2.6
时,以下内容开箱即用:
(1..30).cover?(2..3)
#=> true
答案 1 :(得分:5)
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
操作线相当于:
r1.first <= r2.last && r1.last >= r2.first
我通常会尽量避免否定,但在这种情况下,我认为用它读得更好。
另一种方式:
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
操作线相当于:
([r1.first, r2.first].min..[r1.last, r2.last].max).size < r1.size + r2.size
同样,我更喜欢带有否定的那个。
答案 2 :(得分:3)
虽然转换可能会浪费,但语义上比较集合似乎最有意义:
Set.new(1..30).superset?(Set.new(2..3))
#=> true
Set.new(1..30).superset?(Set.new(0..3))
#=> false
如果您不想这样做,可以执行以下操作(r1
和r2
为范围):
r1.cover?(r2.min) && r1.cover?(r2.max)
答案 3 :(得分:0)
您可以使用检查重叠
range1.first < range2.last && range2.first < range1.last
您可以将其添加为范围的实例方法或作为数据中某处的辅助方法。
来源:https://stackoverflow.com/a/325964/4091324
答案 4 :(得分:0)
在轨道上,您可以使用(1..3).overlaps?(2..4) # true
答案 5 :(得分:0)
如果你想要 Rails 实现,你可以使用
class Range
def overlaps?(other)
cover?(other.first) || other.cover?(first)
end
end
(1..5).overlaps?(4..6) # => true
(1..5).overlaps?(7..9) # => false