Skip to content

Commit e9b503f

Browse files
shouichinobu
authored andcommitted
[Feature #19839] Add Range#overlap?
Add a method that returns true if two range overlap, otherwise false. ``` (0..10).overlap?(5..15) #=> true (0..10).overlap?(20..30) #=> false ```
1 parent 7d08dbd commit e9b503f

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

range.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,6 +2151,34 @@ range_count(int argc, VALUE *argv, VALUE range)
21512151
}
21522152
}
21532153

2154+
/*
2155+
* call-seq:
2156+
* overlap?(range) -> true or false
2157+
*
2158+
* Returns +true+ if +range+ overlaps with +self+, +false+ otherwise:
2159+
*
2160+
* (0..2).overlap?(1..3) #=> true
2161+
* (0..2).overlap?(3..4) #=> false
2162+
* (0..).overlap?(..0) #=> true
2163+
*
2164+
* Related: Range#cover?.
2165+
*/
2166+
2167+
static VALUE
2168+
range_overlap(VALUE range, VALUE other)
2169+
{
2170+
if (!rb_obj_is_kind_of(other, rb_cRange)) {
2171+
rb_raise(rb_eTypeError, "argument must be Range");
2172+
}
2173+
2174+
VALUE beg_self, beg_other;
2175+
2176+
beg_self = RANGE_BEG(range);
2177+
beg_other = RANGE_BEG(other);
2178+
2179+
return RBOOL(rb_equal(beg_self, beg_other) || range_cover(range, beg_other) || range_cover(other, beg_self));
2180+
}
2181+
21542182
/* A \Range object represents a collection of values
21552183
* that are between given begin and end values.
21562184
*
@@ -2417,4 +2445,5 @@ Init_Range(void)
24172445
rb_define_method(rb_cRange, "include?", range_include, 1);
24182446
rb_define_method(rb_cRange, "cover?", range_cover, 1);
24192447
rb_define_method(rb_cRange, "count", range_count, -1);
2448+
rb_define_method(rb_cRange, "overlap?", range_overlap, 1);
24202449
}

test/ruby/test_range.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,4 +1051,32 @@ def test_beginless_range_iteration
10511051
def test_count
10521052
assert_equal(Float::INFINITY, (1..).count)
10531053
end
1054+
1055+
def test_overlap?
1056+
assert_not_operator(0..2, :overlap?, -2..-1)
1057+
assert_not_operator(0..2, :overlap?, -2...0)
1058+
assert_operator(0..2, :overlap?, -1..0)
1059+
assert_operator(0..2, :overlap?, 1..2)
1060+
assert_operator(0..2, :overlap?, 2..3)
1061+
assert_not_operator(0..2, :overlap?, 3..4)
1062+
assert_not_operator(0...2, :overlap?, 2..3)
1063+
1064+
assert_operator(..0, :overlap?, -1..0)
1065+
assert_operator(...0, :overlap?, -1..0)
1066+
assert_operator(..0, :overlap?, 0..1)
1067+
assert_operator(..0, :overlap?, ..1)
1068+
assert_not_operator(..0, :overlap?, 1..2)
1069+
assert_not_operator(...0, :overlap?, 0..1)
1070+
1071+
assert_not_operator(0.., :overlap?, -2..-1)
1072+
assert_not_operator(0.., :overlap?, ...0)
1073+
assert_operator(0.., :overlap?, -1..0)
1074+
assert_operator(0.., :overlap?, ..0)
1075+
assert_operator(0.., :overlap?, 0..1)
1076+
assert_operator(0.., :overlap?, 1..2)
1077+
assert_operator(0.., :overlap?, 1..)
1078+
1079+
assert_raise(TypeError) { (0..).overlap?(1) }
1080+
assert_raise(TypeError) { (0..).overlap?(nil) }
1081+
end
10541082
end

0 commit comments

Comments
 (0)