如果我有两个重叠的范围:
x = 1..10
y = 5..15
当我说:
puts x.include? y
输出是:
false
因为这两个范围只是部分重叠。
但如果我希望它在两个范围之间存在部分重叠时为“真”,那我该如何写呢?换句话说,我需要一种方法来知道一个范围何时包含另一个范围的子集。我假设有一种优雅的方式在Ruby中编写它,但我能想到的唯一解决方案是冗长的。
答案 0 :(得分:60)
有效的方法是比较限制
(x.first <= y.last) and (y.first <= x.last)
答案 1 :(得分:8)
使用大范围时要小心,但这是一种优雅的方法:
(x.to_a & y.to_a).empty?
答案 2 :(得分:2)
您还可以将范围转换为sets,因为您基本上是在这里设置交集。如果你处理两个以上的范围,可能会更容易。
x = (1..10).to_set
y = (5..15).to_set
!(x & y).empty? #returns true (true == overlap, false == no overlap)
答案 3 :(得分: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]]
答案 4 :(得分:1)
如果某个范围包含第二个范围的开头或结尾,则它们会重叠。
(x === y.first) or (x === y.last)
与此相同:
x.include?(y.first) or x.include?(y.last)
答案 5 :(得分:1)
但如果我希望它在两个范围之间存在部分重叠时为“真”, 我该怎么写呢?
您可以将范围转换为数组,并使用&
运算符(连接)。这将返回一个新数组,其中包含两个数组中的所有元素。如果结果数组不为空,则意味着存在一些重叠元素:
def overlap?(range_1, range_2)
!(range_1.to_a & range_2.to_a).empty?
end
答案 6 :(得分:1)
如果您正在检查重叠,那么我只是做
(x.include? y.first) or (x.include? y.last)
因为一个范围必须至少包括另一个范围的一端。这比我接受的结合答案更直观,但不如MarkusQ的限制比较效率高。
答案 7 :(得分:0)
Rails有Range#overlaps?
def overlaps?(other)
cover?(other.first) || other.cover?(first)
end
答案 8 :(得分:0)
如果您使用的是Ruby 2.6,则可以将Range#cover?
与另一个Range
一起使用。
(1..5).cover?(2..3) #=> true
(1..5).cover?(0..6) #=> false
(1..5).cover?(1...6) #=> true
答案 9 :(得分:-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}