diff --git a/intervalset.go b/intervalset.go index 2af281b..b9371fb 100644 --- a/intervalset.go +++ b/intervalset.go @@ -59,36 +59,53 @@ func (r Interval[E]) Set() Set[E] { // a Set. type Set[E Elem[E]] []Interval[E] -// Collect returns the set of elements that are in any of rs. +// Collect returns the set of elements that are in any of s. // -// Collect performs better if Intervals in rs are Low-sorted in ascending order. -func Collect[E Elem[E]](rs ...Interval[E]) Set[E] { - var s Set[E] +// Collect performs better if s are sorted in ascending order by the Low field. +func Collect[E Elem[E]](s ...Interval[E]) Set[E] { + return CollectInto(nil, s...) +} + +// CollectInto returns the set of elements that are in any of s, overwriting x. +// +// CollectInto performs better if s are sorted in ascending order by the Low +// field. +func CollectInto[E Elem[E]](x Set[E], s ...Interval[E]) Set[E] { + x = x[:0] - for _, r := range rs { - if len(s) == 0 { + for _, r := range s { + if len(x) == 0 { if r.Low.Compare(r.High) < 0 { - s = append(s, r) + x = append(x, r) } continue } - switch r1 := &s[len(s)-1]; { + switch r1 := &x[len(x)-1]; { case r1.High.Compare(r.Low) < 0: if r.Low.Compare(r.High) < 0 { - s = append(s, r) + x = append(x, r) } case r1.Low.Compare(r.Low) <= 0: if r1.High.Compare(r.High) < 0 { r1.High = r.High } default: - s.Add(r) + x.Add(r) } } - return s + return x +} + +// Normalize modifies s to return a normalized set. +// It works like Set[E](s) with normalization. +// +// Normalize performs better if s are sorted in ascending order by the Low +// field. +func Normalize[E Elem[E]](s []Interval[E]) Set[E] { + return CollectInto(s, s...) } // Add adds range [r.Low, r.High) into x. diff --git a/intervalset_test.go b/intervalset_test.go index 3fd1269..e0908dc 100644 --- a/intervalset_test.go +++ b/intervalset_test.go @@ -41,6 +41,10 @@ func TestCreation(t *testing.T) { Collect(Range[E](5, 1), Range[E](3, 7), Range[E](11, 9), Range[E](5, 1)), Set[E]{{3, 7}}, }, + { + Normalize([]Interval[E]{{1, 7}, {5, 13}, {11, 17}}), + Set[E]{{1, 17}}, + }, } for i, c := range testCases {