检查Ruby中两个范围是否重叠

kuhbmx9i  于 2023-04-20  发布在  Ruby
关注(0)|答案(6)|浏览(80)

我知道我能做到:

(1..30).cover?(2)
=> true

但是当我尝试对另一个范围做同样的事情时,它总是返回false:

(1..30).cover?(2..3)
=> false

所以我的问题是-在ruby中有没有什么优雅的方法来比较两个范围?在我的例子中,我想检查两个DateTime范围是否重叠。

de90aj5v

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
kh212irz

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

再说一次,我更喜欢否定的那个。

k10s72fa

k10s72fa3#

在rails中,可以使用(1..3).overlaps?(2..4) # true
https://apidock.com/rails/Range/overlaps

c86crjj0

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
46qrfjad

46qrfjad5#

虽然转换可能很浪费,但从语义上比较集合似乎最有意义:

Set.new(1..30).superset?(Set.new(2..3))
#=> true
Set.new(1..30).superset?(Set.new(0..3))
#=> false

如果你不想这样做,你可以这样做(r1r2是范围):

r1.cover?(r2.min) && r1.cover?(r2.max)
t30tvxxf

t30tvxxf6#

可以使用range1.first < range2.last && range2.first < range1.last选中重叠
你可以将它作为range的示例方法或作为data.source中的helper方法添加到数据库中。https://stackoverflow.com/a/325964/4091324

相关问题