我知道我能做到:
(1..30).cover?(2) => true
但是当我尝试对另一个范围做同样的事情时,它总是返回false:
(1..30).cover?(2..3) => false
所以我的问题是-在ruby中有没有什么优雅的方法来比较两个范围?在我的例子中,我想检查两个DateTime范围是否重叠。
de90aj5v1#
对于给定范围A,两个范围重叠,当:1.范围B在范围A内开始,1.范围B在范围A内结束,或1.范围B在范围A之前开始并且在范围A之后结束。示例:
Range A |-----| |-----| Case 1 |-----| Case 2 |-| Case 1 + 2 |---------| Case 3
仔细看,规则是:当范围B在范围A结束之前开始并且范围B在范围A开始之后结束时,两个范围重叠。
def ranges_overlap?(range_a, range_b) range_b.begin <= range_a.end && range_a.begin <= range_b.end end
kh212irz2#
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
再说一次,我更喜欢否定的那个。
k10s72fa3#
在rails中,可以使用(1..3).overlaps?(2..4) # truehttps://apidock.com/rails/Range/overlaps
(1..3).overlaps?(2..4) # true
c86crjj04#
如果您想要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
46qrfjad5#
虽然转换可能很浪费,但从语义上比较集合似乎最有意义:
Set.new(1..30).superset?(Set.new(2..3)) #=> true Set.new(1..30).superset?(Set.new(0..3)) #=> false
如果你不想这样做,你可以这样做(r1和r2是范围):
r1
r2
r1.cover?(r2.min) && r1.cover?(r2.max)
t30tvxxf6#
可以使用range1.first < range2.last && range2.first < range1.last选中重叠你可以将它作为range的示例方法或作为data.source中的helper方法添加到数据库中。https://stackoverflow.com/a/325964/4091324
range1.first < range2.last && range2.first < range1.last
6条答案
按热度按时间de90aj5v1#
对于给定范围A,两个范围重叠,当:
1.范围B在范围A内开始,
1.范围B在范围A内结束,或
1.范围B在范围A之前开始并且在范围A之后结束。
示例:
仔细看,规则是:当范围B在范围A结束之前开始并且范围B在范围A开始之后结束时,两个范围重叠。
kh212irz2#
手术线相当于:
我通常尽量避免否定,但在这种情况下,我认为它读起来更好。
另一种方式:
手术线相当于:
再说一次,我更喜欢否定的那个。
k10s72fa3#
在rails中,可以使用
(1..3).overlaps?(2..4) # true
https://apidock.com/rails/Range/overlaps
c86crjj04#
如果您想要Rails实现,可以使用
46qrfjad5#
虽然转换可能很浪费,但从语义上比较集合似乎最有意义:
如果你不想这样做,你可以这样做(
r1
和r2
是范围):t30tvxxf6#
可以使用
range1.first < range2.last && range2.first < range1.last
选中重叠你可以将它作为range的示例方法或作为data.source中的helper方法添加到数据库中。https://stackoverflow.com/a/325964/4091324