I know that I can do:
(1..30).cover?(2)
=> true
But when I try to do the same with another range it always returns false:
(1..30).cover?(2..3)
=> false
So my question is - is there any elegant way to compare two ranges in ruby? In my case I want to check if two DateTime-ranges overlap. Thanks in advance.
You can do this by swapping the ranges if necessary up front. Then, you can detect overlap if the second range start is: less than or equal to the first range end (if ranges are inclusive, containing both the start and end times); or. less than (if ranges are inclusive of start and exclusive of end).
If both ranges have at least one common point, then we say that they're overlapping. In other words, we say that two ranges and are overlapping if: On the other hand, non-overlapping ranges don't have any points in common.
Overlap = min(A2, B2) - max(A1, B1) + 1. In other words, the overlap of two integer intervals is a difference between the minimum value of the two upper boundaries and the maximum value of the two lower boundaries, plus 1.
SQL Query using Lag Function for OverLapping Time Intervals SQL programmers now can use SQL LAG() function to compare all table rows with the previous row when ordered by ID column.
Two ranges overlap for a given range A when:
Examples:
Range A |-----|
|-----| Case 1
|-----| Case 2
|-| Case 1 + 2
|---------| Case 3
Looking closer the rule is: Two ranges overlap when Range B starts before the range A ends and range B ends after the range A starts.
def ranges_overlap?(range_a, range_b)
range_b.begin <= range_a.end && range_a.begin <= range_b.end
end
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
The operative line is equivalent to:
r1.first <= r2.last && r1.last >= r2.first
I normally try to avoid negation, but in this case I think it reads better with it.
Another way:
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
The operative line is equivalent to:
([r1.first, r2.first].min..[r1.last, r2.last].max).size < r1.size + r2.size
Again, I prefer the one with negation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With