chore: Add collection type - OrderedSet (#63469)

It is missing from the stdlib and the orderedmap library we're using.
This commit is contained in:
Varun Gandhi 2024-06-25 21:13:14 +08:00 committed by GitHub
parent ec90be4274
commit e9108b33f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 77 additions and 0 deletions

View File

@ -4,6 +4,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "collections",
srcs = [
"ordered_set.go",
"set.go",
"slice_utils.go",
],
@ -11,6 +12,7 @@ go_library(
visibility = ["//:__subpackages__"],
deps = [
"//lib/errors",
"@com_github_wk8_go_ordered_map_v2//:go-ordered-map",
"@org_golang_x_exp//constraints",
"@org_golang_x_exp//maps",
],
@ -20,6 +22,7 @@ go_test(
name = "collections_test",
timeout = "short",
srcs = [
"ordered_set_test.go",
"set_test.go",
"slice_utils_test.go",
],

View File

@ -0,0 +1,45 @@
package collections
import orderedmap "github.com/wk8/go-ordered-map/v2"
// OrderedSet keeps track of values in insertion order.
type OrderedSet[T comparable] orderedmap.OrderedMap[T, struct{}]
// NewOrderedSet creates a OrderedSet[T] with the given values.
// T must be a comparable type (implementing sort.Interface or == operator).
func NewOrderedSet[T comparable](values ...T) *OrderedSet[T] {
s := OrderedSet[T](*orderedmap.New[T, struct{}]())
s.Add(values...)
return &s
}
func (s *OrderedSet[T]) impl() *orderedmap.OrderedMap[T, struct{}] {
return (*orderedmap.OrderedMap[T, struct{}])(s)
}
func (s *OrderedSet[T]) Add(values ...T) {
for _, v := range values {
s.impl().Set(v, struct{}{})
}
}
func (s *OrderedSet[T]) Remove(values ...T) {
for _, v := range values {
s.impl().Delete(v)
}
}
func (s *OrderedSet[T]) Has(value T) bool {
_, found := s.impl().Get(value)
return found
}
// Values returns a slice with all the values in the set.
// The values are returned in insertion order.
func (s *OrderedSet[T]) Values() []T {
out := make([]T, 0, s.impl().Len())
for x := s.impl().Oldest(); x != nil; x = x.Next() {
out = append(out, x.Key)
}
return out
}

View File

@ -0,0 +1,29 @@
package collections
import (
"testing"
"github.com/stretchr/testify/require"
"pgregory.net/rapid"
)
func TestOrderedSet(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
data := rapid.SliceOfN(rapid.IntRange(-3, 6), 0, 10).Draw(t, "data")
set := NewSet(data...)
uniquedData := set.Values()
ordset := NewOrderedSet(uniquedData...)
require.Equal(t, uniquedData, ordset.Values())
otherData := rapid.SliceOfN(rapid.IntRange(-5, 5), 10, 10).Draw(t, "data")
for _, x := range otherData {
require.Equal(t, set.Has(x), ordset.Has(x))
}
for _, x := range uniquedData {
require.True(t, ordset.Has(x))
ordset.Remove(x)
require.False(t, ordset.Has(x))
}
})
}