(Ruby) How do you check whether a range contains a

2019-03-14 23:34发布

If I have two ranges that overlap:

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

When I say:

puts x.include? y 

the output is:

false 

because the two ranges only overlap partially.

But if I want it to be "true" when there is partial overlap between two ranges, how would I write that? In other words I need a way to know when one range contains a subset of another range. I assume there's an elegant way to write this in Ruby but the only solutions I can think of are verbose.

标签: ruby range
9条回答
疯言疯语
2楼-- · 2019-03-15 00:02

Be careful using this with large ranges but this is an elegant way to do it:

(x.to_a & y.to_a).empty?
查看更多
一纸荒年 Trace。
3楼-- · 2019-03-15 00:04

You could also convert the ranges to sets, since you're basically doing set intersection here. Might be easier if you are dealing with more than two ranges.

x = (1..10).to_set
y = (5..15).to_set
!(x & y).empty? #returns true (true == overlap, false == no overlap)
查看更多
淡お忘
4楼-- · 2019-03-15 00:04

Some helpful enumerable methods:

# 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}
查看更多
一夜七次
5楼-- · 2019-03-15 00:07

If a range includes either the beginning or the end of a second range, then they overlap.

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

is the same as this:

x.include?(y.first) or x.include?(y.last)
查看更多
ら.Afraid
6楼-- · 2019-03-15 00:17

This method can be used to test overlap between multiple ranges in an efficient way:

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]]
查看更多
男人必须洒脱
7楼-- · 2019-03-15 00:20

But if I want it to be "true" when there is partial overlap between two ranges, how would I write that?

You can convert the ranges to an array, and use the & operator (conjunction). This returns a new array with all the elements occuring in both arrays. If the resulting array is not empty, that means, that there are some overlapping elements:

def overlap?(range_1, range_2)
  !(range_1.to_a & range_2.to_a).empty?
end
查看更多
登录 后发表回答