82 lines
2.3 KiB
Go
82 lines
2.3 KiB
Go
package interval
|
|
|
|
import "github.com/labstack/gommon/log"
|
|
|
|
func (intvls *intervals) Merge() []*Interval {
|
|
if intvls.MergeList == nil {
|
|
intvls.MergeList = intvls.calculateMerged()
|
|
}
|
|
return intvls.MergeList
|
|
}
|
|
|
|
func (intvls *intervals) calculateMerged() []*Interval {
|
|
list := []*Interval{}
|
|
if len(intvls.Intervals) == 0 {
|
|
return list
|
|
}
|
|
|
|
// sort intervals (if necessary)
|
|
intvls.Sort()
|
|
|
|
var currentMinLow int
|
|
var currentMaxHigh int
|
|
firstInitDone := false
|
|
for _, intvl := range intvls.Intervals {
|
|
// convert if necessary exclusive low/high values into inclusive ones
|
|
low, high, err := intvls.getInclusives(intvl.Low, intvl.High)
|
|
if err != nil {
|
|
log.Errorf("calculateMerged - unable to get inclusives: %v", err)
|
|
continue
|
|
}
|
|
|
|
// in the first iteration it's for sure that don't exists merge, we just initialize variables
|
|
if !firstInitDone {
|
|
currentMinLow = low
|
|
currentMaxHigh = high
|
|
firstInitDone = true
|
|
continue
|
|
}
|
|
|
|
// in case the current interval is overlapped or consecutive to the previous one, we need to update variables
|
|
// and keep going and process the next interval
|
|
if areSegmentsConsecutivesOrOverlapped(low, high, currentMinLow, currentMaxHigh) {
|
|
// update control variables if necessary
|
|
if low < currentMinLow {
|
|
currentMinLow = low
|
|
}
|
|
if high > currentMaxHigh {
|
|
currentMaxHigh = high
|
|
}
|
|
continue
|
|
}
|
|
|
|
// here the segments are not consecutive or overlapped so we close this merged segment (add to the list)
|
|
list = append(list, &Interval{Low: currentMinLow, High: currentMaxHigh})
|
|
|
|
// update control variables
|
|
currentMinLow = low
|
|
currentMaxHigh = high
|
|
}
|
|
// the last segment is pending to be added to the list
|
|
list = append(list, &Interval{Low: currentMinLow, High: currentMaxHigh})
|
|
return list
|
|
}
|
|
|
|
func areSegmentsOverlapped(low, high, lastLow, lastHigh int) bool {
|
|
if isLowInBetweenInclusive(low, high, lastLow, lastHigh) {
|
|
return true
|
|
}
|
|
if isHighInBetweenInclusive(low, high, lastLow, lastHigh) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func areSegmentsConsecutives(low, high, lastLow, lastHigh int) bool {
|
|
return ((lastHigh + 1) == low) || ((high + 1) == lastLow)
|
|
}
|
|
|
|
func areSegmentsConsecutivesOrOverlapped(low, high, lastLow, lastHigh int) bool {
|
|
return areSegmentsOverlapped(low, high, lastLow, lastHigh) || areSegmentsConsecutives(low, high, lastLow, lastHigh)
|
|
}
|