util/set: add OfSliceView constructor and Set.AddSliceView
Building a Set from a views.Slice previously required set.Of(v.AsSlice()...), which allocates an intermediate slice copy before allocating the set. Add OfSliceView and AddSliceView to populate a set directly from the view, mirroring the existing AddSlice/AddSeq/AddSet family. Updates tailscale/corp#45499 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I3f2a9d417c60be8e5f1acd42708e2f9a4d6c1b7e
This commit is contained in:
committed by
Brad Fitzpatrick
parent
e48e7b730a
commit
d0b4d44963
@@ -10,6 +10,8 @@ import (
|
|||||||
"maps"
|
"maps"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"tailscale.com/types/views"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set is a set of T.
|
// Set is a set of T.
|
||||||
@@ -27,6 +29,13 @@ func Of[T comparable](slice ...T) Set[T] {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OfSliceView returns a new set constructed from the elements in v.
|
||||||
|
func OfSliceView[T comparable](v views.Slice[T]) Set[T] {
|
||||||
|
s := make(Set[T], v.Len())
|
||||||
|
s.AddSliceView(v)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// Clone returns a new set cloned from the elements in s.
|
// Clone returns a new set cloned from the elements in s.
|
||||||
func (s Set[T]) Clone() Set[T] {
|
func (s Set[T]) Clone() Set[T] {
|
||||||
return maps.Clone(s)
|
return maps.Clone(s)
|
||||||
@@ -56,6 +65,13 @@ func (s Set[T]) AddSlice(es []T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddSliceView adds each element of v to s.
|
||||||
|
func (s Set[T]) AddSliceView(v views.Slice[T]) {
|
||||||
|
for _, e := range v.All() {
|
||||||
|
s.Add(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AddSet adds each element of es to s.
|
// AddSet adds each element of es to s.
|
||||||
func (s Set[T]) AddSet(es Set[T]) {
|
func (s Set[T]) AddSet(es Set[T]) {
|
||||||
for e := range es {
|
for e := range es {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"tailscale.com/types/views"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSet(t *testing.T) {
|
func TestSet(t *testing.T) {
|
||||||
@@ -98,6 +100,18 @@ func TestSetOf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOfSliceView(t *testing.T) {
|
||||||
|
s := OfSliceView(views.SliceOf([]int{1, 2, 3, 4, 4, 1}))
|
||||||
|
if s.Len() != 4 {
|
||||||
|
t.Errorf("wrong len %d; want 4", s.Len())
|
||||||
|
}
|
||||||
|
for _, n := range []int{1, 2, 3, 4} {
|
||||||
|
if !s.Contains(n) {
|
||||||
|
t.Errorf("should contain %d", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEqual(t *testing.T) {
|
func TestEqual(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user