Reputation: 1336
How can I simply check if a range is a subrange of another ?
range1 in range2
will not work as expected.
Upvotes: 17
Views: 15431
Reputation: 602
I was working on a similar problem: how to find if two ranges overlap. Hence, the order of ranges introduced in the function was a limitation for me (the order should not affect). This is the solution I propose (inspired by @jonrsharpe answer):
def range_overlap(range1, range2):
"""Whether range1 and range2 overlap."""
x1, x2 = range1.start, range1.stop
y1, y2 = range2.start, range2.stop
return x1 <= y2 and y1 <= x2
a = range(20, 25, 2)
b = range(23, 25, 3) # different step does not matter
print(list(a), list(b)) # [20, 22, 24] [23]
range_overlap(a, b) # True
In case any range is empty:
# if range1 is non-empty and range2 is empty
a = range(20, 25, 1)
b = range(22, 22, 3) # empty but the range start and end overlap
assert range_overlap(a, b) == range_overlap(a, b)
range_overlap(a, b)
# True
Upvotes: 4
Reputation: 402
This is the most readable imo, but inefficient:
all(e in range2 for e in range1)
I think this would be the most efficient if both ranges have the same step:
range1[0] in range2 and range1[-1] in range2
Upvotes: 3
Reputation: 122096
You can do it in O(1)
, as follows:
def range_subset(range1, range2):
"""Whether range1 is a subset of range2."""
if not range1:
return True # empty range is subset of anything
if not range2:
return False # non-empty range can't be subset of empty range
if len(range1) > 1 and range1.step % range2.step:
return False # must have a single value or integer multiple step
return range1.start in range2 and range1[-1] in range2
In use:
>>> range_subset(range(0, 1), range(0, 4))
True
Upvotes: 22