时间取并交集的小工具(Go)

我们常会遇到比如司机在线时长统计的这种类型计算,

求并集[1,2],[4,5],[5,9],结果是[1,2],[4,9]

求所有的交集为[]

但是求相交部分为[1,2],[5,5],

三个类型,对应下面三个小函数

type TimeInterval struct {
	Start int
	End int
}
type TimeSlice []TimeInterval
// 求全局的并集
func (ts TimeSlice) Union()TimeSlice{
	if len(ts) <= 1{
		return ts
	}
	sort.SliceStable(ts, func(i, j int) bool {
		return ts[i].Start <= ts[j].Start
	})
	res := TimeSlice{ts[0]}
	for key, val := range ts{
		if key == 0{
			continue
		}
		if val.Start >= res[len(res)-1].Start && val.Start < res[len(res)-1].End{
			if val.End > res[len(res)-1].End{
				res[len(res)-1].End = val.End
			}
		}else{
			res = append(res, val)
		}
	}
	return res
}
// 求全局的交集
func (ts TimeSlice)Intersect()TimeSlice{
	if len(ts) <= 1{
		return ts
	}
	sort.SliceStable(ts, func(i, j int) bool {
		return ts[i].Start < ts[j].Start
	})
	res := TimeSlice{ts[0]}
	for key, val := range ts{
		if key == 0{
			continue
		}
		if val.Start >= res[0].Start && val.Start <= res[0].End{
			res[0].Start = val.Start
			if val.Start < res[0].End{
				res[0].End = val.End
			}
		}else {
			return res[:0]
		}
	}
	return res
}

// 求部分的交集
func (ts TimeSlice)IntersectSome()TimeSlice{
	if len(ts) <= 1{
		return ts
	}
	sort.SliceStable(ts, func(i, j int) bool {
		return ts[i].Start < ts[j].Start
	})
	res := TimeSlice{ts[0]}
	for key, val := range ts{
		if key == 0{
			continue
		}
		if val.Start >= res[len(res)-1].Start && val.Start <= res[len(res)-1].End{
			res[len(res)-1].Start = val.Start
			if val.Start < res[len(res)-1].End{
				res[len(res)-1].End = val.End
			}
		}else {
			res = append(res, val)
		}
	}
	return res
}
func RunMergeInterval(){
	case1:= TimeSlice{TimeInterval{1,2}, TimeInterval{2,5}, TimeInterval{1,9},TimeInterval{10,100},TimeInterval{11,200}}
	case2:= TimeSlice{TimeInterval{1,2}, TimeInterval{2,5}, TimeInterval{1,9},TimeInterval{1,100},TimeInterval{1,200}}

	case3:= TimeSlice{TimeInterval{1,2}, TimeInterval{2,5}, TimeInterval{1,9},TimeInterval{1,100},TimeInterval{1,200}}
	// res = [[1 100] [101 102]]
	re := case1.Union()
	fmt.Println(re)
	fmt.Println(case1.Intersect(), case2.Intersect(), case1.IntersectSome(), case3.IntersectSome())
        //[{1 9} {10 200}]
     //[] [{2 5}] [{2 2} {11 200}] [{2 5}]
}    

  

posted @ 2021-03-21 22:40  布尔先生  阅读(256)  评论(0编辑  收藏  举报