How to Find Overlapping Ranges in Python
Determining the overlap between two ranges of numbers is a common task in programming, often used in scheduling, data analysis, and interval calculations.
This guide explains how to find the overlapping portion of two ranges in Python, and how to check if two ranges overlap.
Finding Range Overlap (Recommended Method)
The most efficient and readable way to find the overlapping range is to use max()
on the start values and min()
on the end values. This avoids unnecessary iterations or conversions.
def find_range_overlap(range1, range2):
"""
Finds the overlapping range between two ranges.
Args:
range1: The first range (e.g., range(1, 7)).
range2: The second range (e.g., range(5, 10)).
Returns:
A list of integers representing the overlapping range, or
an empty list if there's no overlap.
"""
start = max(range1.start, range2.start) # Latest start
end = min(range1.stop, range2.stop) # Earliest end
# Ensure that a valid range can be made. If end < start,
# then the ranges don't overlap at all.
return list(range(start, end))
x = range(1, 7)
y = range(5, 10)
overlap = find_range_overlap(x, y)
print(overlap) # Output: [5, 6]
x = range(2, 7)
y = range(10, 15)
overlap = find_range_overlap(x, y)
print(overlap) # Output: [] (no overlap)
- The function takes two
range
objects as inputs. start = max(range1.start, range2.start)
: Determines the later of the two starting points. This is the start of the overlap.end = min(range1.stop, range2.stop)
: Determines the earlier of the two ending points. This is the end of the overlap.list(range(start, end))
: Creates a range representing the overlap and converts it into a list, so that an empty list can be returned if there is no overlapping, or if there is, the result is more convenient to use.- The function will return a list, as it is easier to test if the returned object contains any value.
Checking if Two Ranges Overlap
If you only need to know if two ranges overlap, and don't need the actual overlapping range, you can simplify the function:
def ranges_overlap(range1, range2):
"""Checks if two ranges overlap."""
return max(range1.start, range2.start) < min(range1.stop, range2.stop)
x = range(2, 7)
y = range(4, 12)
print(ranges_overlap(x, y)) # Output: True
x = range(2, 7)
y = range(10, 15)
print(ranges_overlap(x, y)) # Output: False
- This function directly compares the start and stop values to determine overlap without constructing the overlapping range. This is more efficient if you only need a boolean result.
Using Set Intersection (Less Efficient, Order Not Preserved)
While you can use set intersection to find common elements, it's significantly less efficient than the direct range comparison and doesn't preserve the order of the range:
def find_range_overlap_set(range1, range2):
return list(set(range1).intersection(range2))
x = range(2, 10)
y = range(7, 15)
overlap = find_range_overlap_set(x, y)
print(overlap) # Output: [8, 9, 7] (Order NOT guaranteed)
x = range(1, 7)
y = range(5, 10)
overlap = find_range_overlap_set(x,y)
print(overlap) # Output: [5, 6] (order NOT guaranteed)
- This converts the ranges to sets, finds the intersection (common elements), and then converts the result back to a list.
- Drawbacks:
- Inefficient: Creating sets from large ranges is slow.
- Order not preserved: Sets are unordered, so you lose the original sequence of the overlapping range.
- Because of that, using this approach is not recommended.