Basically, you can walk through the ranges and use a stack to keep track of the properties set. Create a list of start and end points in the ranges, sort the list by start/end point value, then loop over them. For each item, finish the previous range by setting the end point and create a new range. If the item starts a new range, push the item to the stack and set the new range's properties to the item's properties. If the item ends a range, pop from the stack and set the new range's properties to the properties of the item now at the top of the stack.
Here's some Python code (all I have available at the moment) that seems to work.
query_result = [(1, 1000, 1), (100, 200, 2), (250, 350, 3), (300, 350, 4)]
range_endpoints = list()
for i in query_result:
t = ("min", i[0], i[2])
range_endpoints.append(t)
t = ("max", i[1], i[2])
range_endpoints.append(t)
def keyfunc(t):
return t[1]
range_endpoints.sort(key=keyfunc)
print(range_endpoints)
stack = list()
stack.append((None, None, None)) # Dummy value that marks the start and end of the set of ranges
final_ranges = list()
first_endpoint = range_endpoints.pop(0)
current_range = [first_endpoint[1], None, first_endpoint[2]]
stack.append(first_endpoint)
for t in range_endpoints:
if t[0] == "min":
current_range[1] = t[1] - 1
final_ranges.append(current_range)
current_range = [t[1], None, t[2]]
stack.append(t)
elif t[0] == "max":
# Check for end of a range that ends at the same point as the previous range
if t[1] > final_ranges[-1][1]:
current_range[1] = t[1]
final_ranges.append(current_range)
stack.pop()
current_range = [t[1] + 1, None, stack[-1][2]]
print(final_ranges)