16

如果我有两个重叠的范围:

x = 1..10
y = 5..15

当我说:

puts x.include? y 

输出是:

false 

因为这两个范围只是部分重叠。

但是,如果我希望在两个范围之间存在部分重叠时它是“真实的”,我该怎么写呢?换句话说,我需要一种方法来知道一个范围何时包含另一个范围的子集。我认为有一种用 Ruby 编写的优雅方法,但我能想到的唯一解决方案是冗长的。

4

10 回答 10

64

有效的方法是比较限制

(x.first <= y.last) and (y.first <= x.last)
于 2009-03-30T23:30:41.970 回答
8

在大范围内使用它时要小心,但这是一种优雅的方法:

(x.to_a & y.to_a).empty?
于 2009-11-12T02:17:03.877 回答
4

如果您使用的是 Ruby 2.6,则可以使用Range#cover?另一个Range.

(1..5).cover?(2..3)     #=> true
(1..5).cover?(0..6)     #=> false
(1..5).cover?(1...6)    #=> true
于 2019-05-24T11:43:32.953 回答
2

您也可以将范围转换为sets,因为您基本上是在这里进行 set 交集。如果您要处理两个以上的范围,可能会更容易。

x = (1..10).to_set
y = (5..15).to_set
!(x & y).empty? #returns true (true == overlap, false == no overlap)
于 2011-05-29T17:15:48.587 回答
2

此方法可用于以有效的方式测试多个范围之间的重叠:

def range_overlap?(ranges)
  sorted_ranges = ranges.sort
  sorted_ranges.each_cons(2).each do |r1, r2|
    return true if r2.first <= r1.last
  end
  return false
end


def test(r)
  puts r.inspect, range_overlap?(r)
  puts '================'
  r = r.reverse
  puts r.inspect, range_overlap?(r)
  puts '================'
end


test [[1,9], [10, 33]]
test [[1,10], [5, 8]]
test [[1,10], [10, 33]]
于 2012-05-21T11:55:49.900 回答
1

如果一个范围包括第二个范围的开头或结尾,则它们重叠。

(x === y.first) or (x === y.last)

与此相同:

x.include?(y.first) or x.include?(y.last)
于 2009-03-31T01:07:28.617 回答
1

但是,如果我希望在两个范围之间存在部分重叠时它是“真实的”,我该怎么写呢?

您可以将范围转换为数组,并使用&运算符(连词)。这将返回一个新数组,其中包含两个数组中出现的所有元素。如果结果数组不为空,则意味着存在一些重叠元素:

def overlap?(range_1, range_2)
  !(range_1.to_a & range_2.to_a).empty?
end
于 2009-03-31T16:07:37.330 回答
1

如果您正在检查重叠,那么我会做

(x.include? y.first) or (x.include? y.last)

因为一个范围必须至少包括另一个范围的一端。这对我来说比公认的结合答案更直观,尽管不如 MarkusQ 的极限比较有效。

于 2009-08-26T20:44:52.883 回答
0

Rails 有Range#overlaps?

def overlaps?(other)
  cover?(other.first) || other.cover?(first)
end
于 2016-07-25T21:14:04.777 回答
-1

一些有用的可枚举方法:

# x is a 'subset' of y
x.all?{|n| y.include? n}
# x and y overlap
x.any?{|n| y.include? n}
# x and y do not overlap
x.none?{|n| y.include? n}
# x and y overlap one time
x.one?{|n| y.include? n}
于 2012-01-30T04:37:00.597 回答