Currently, I have intervals of:
temp_tuple = [[-25, -14], [-21, -16], [-20, -15], [-10, -7], [-8, -5], [-6, -3], [2, 4], [2, 3], [3, 6], [12, 15], [13, 18],
The salient feature of the solution below is to run a list called final
parallel to the input list. Before entering the for
loop, the final
list inserts the first array item in it. Then starts the comparison. That's it!
def merger(a):
final=[]
final.append(a[0])
for i in range(1,len(a)):
if a[i][0]<=final[-1][1]:
if a[i][1]>final[-1][1]:
low_limit=final[-1][0]
hi_limit=a[i][1]
final.pop()
final.append([low_limit,hi_limit])
if a[i][1]<=final[-1][1]:
low_limit=final[-1][0]
hi_limit=final[-1][1]
final.pop()
final.append([low_limit,hi_limit])
if final[-1][0]<a[i][1]<final[-1][1]:
low_limit=a[i][0]
hi_limit=final[-1][1]
final.pop()
final.append([low_limit,hi_limit])
else:
final.append(a[i])
return final
if __name__=="__main__":
array=[[-25, -14], [-21, -16], [-20, -15], [-10, -7], [-8, -5], [-6, -3], [2, 4], [2, 3], [3, 6], [12, 15], [13, 18], [14, 17], [22, 27], [25, 30], [26, 29]]
print(merger(array))
Output:
[[-25, -14], [-10, -3], [2, 6], [12, 18], [22, 30]]
#Given an array of intervals in sorted order and a new interval, return a sorted array after merging the interval
def mergeinter(intervals,newinter):
n = len(intervals)
start = newinter[0]# we mark the start and end of the new interval to be merged
end = newinter[1]
right,left = 0,0
while right < n:# we track where this new interval belongs, i.e. how many interval are to the left of it and how many are to the right
if start <= intervals[right][1]:# we find the first interval before which it fits
if end < intervals[right][0]:# this checks if the interval is disjoint and lies between two given intervals
break# in this case we have nothing to do and go to line 29 directly
start = min(start,intervals[right][0])# if it intersects with the given intervals then we just update and merge the ends
end = max(end,intervals[right][1])
else:# counting how many to the left continuing from line 20
left += 1
right += 1# moving right to find the fit continuation of line 20 and even if we merge in line 25, we go to the next interval before
return intervals[:left] + [(start,end)] + intervals[right:] # we return starting from the next interval
#Given a collection of intervals, merge all overlapping intervals and return sorted list of disjoint intervals.
def merge(I):
I.sort(key:lambda i:i[0])# sorting according to the start of all intervals
res = []# we start from the last of the given arr of lists and check the ends of the intervals and merge from the end
for i in I:
if not res or res[-1][0] < i[1]:# if res is empty then we put an elem in it from I
res.append(i)# if there is no overlap, just add it
else:
res[-1][1] = max(i[1], res[-1][1])# here we merge from the end so that res remains sorted
return res
It makes it a bit easier to process (as in think about) if you instead setup a new list. You additionally also get to keep your original data.
temp_tuple.sort(key=lambda interval: interval[0])
merged = [temp_tuple[0]]
for current in temp_tuple:
previous = merged[-1]
if current[0] <= previous[1]:
previous[1] = max(previous[1], current[1])
else:
merged.append(current)
If you now print(merged)
it would output:
[[-25, -14], [-10, -3], [2, 6], [12, 18], [22, 30]]
This is a numpy solution I came up with:
import numpy as np
def merge_intervals(intervals):
starts = intervals[:,0]
ends = np.maximum.accumulate(intervals[:,1])
valid = np.zeros(len(intervals) + 1, dtype=np.bool)
valid[0] = True
valid[-1] = True
valid[1:-1] = starts[1:] >= ends[:-1]
return np.vstack((starts[:][valid[:-1]], ends[:][valid[1:]])).T
#example
a=[]
a.append([1,3])
a.append([4,10])
a.append([5,12])
a.append([6,8])
a.append([20,33])
a.append([30,35])
b = np.array(a)
print("intervals")
print(b)
print()
print("merged intervals")
print(merge_intervals(b))
Output:
intervals
[[ 1 3]
[ 4 10]
[ 5 12]
[ 6 8]
[20 33]
[30 35]]
merged intervals
[[ 1 3]
[ 4 12]
[20 35]]
Please note that the input array must be sorted by start positions.