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

Pet*_*per 5 ruby

我知道我能做到:

(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范围是否重叠.提前致谢.

spi*_*ann 8

在给定范围A时,两个范围重叠:

  1. 范围B在范围A内开始
  2. 范围B结束于范围A或
  3. 范围B在范围A之前开始,在范围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)


Car*_*and 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
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)

再一次,我更喜欢有否定的那个.


O.V*_*hor 5

在 Rails 中你可以使用(1..3).overlaps?(2..4) # true

https://apidock.com/rails/Range/overlaps


JuJ*_*oDi 5

如果你想要 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)

  • 这应该进入 ruby​​ stdlib ... (2认同)

mec*_*cov 1

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)