Skip to content

Commit

Permalink
add a bunch of set functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ldemailly committed Feb 21, 2023
1 parent 64904e7 commit 6641cac
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
46 changes: 46 additions & 0 deletions dyngeneric.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,37 @@ func SetFromSlice[T comparable](items []T) Set[T] {
return res
}

func (s Set[T]) Clone() Set[T] {
res := make(Set[T], len(s))
for k := range s {
res.Add(k)
}
return res
}

func (s Set[T]) Add(item ...T) {
for _, i := range item {
s[i] = struct{}{}
}
}

func (s Set[T]) Has(item T) bool {
_, found := s[item]
return found
}

func (s Set[T]) Remove(item ...T) {
for _, i := range item {
delete(s, i)
}
}

func NewSet[T comparable](item ...T) Set[T] {
res := make(Set[T], len(item))
res.Add(item...)
return res
}

func (s Set[T]) String() string {
keys := make([]string, 0, len(s))
for k := range s {
Expand All @@ -226,6 +257,21 @@ func (s Set[T]) String() string {
return strings.Join(keys, ",")
}

// RemoveCommon removes elements from both sets that are in both,
// leaving only the delta. Useful for Notifier on Set so that
// oldValue has what has been removed and newValue has what has been added.
func RemoveCommon[T comparable](a, b Set[T]) {
if len(a) > len(b) {
a, b = b, a
}
for e := range a {
if _, found := b[e]; found {
delete(a, e)
delete(b, e)
}
}
}

// Set updates the value from a string representation in a thread-safe manner.
// This operation may return an error if the provided `input` doesn't parse, or the resulting value doesn't pass an
// optional validator.
Expand Down
20 changes: 20 additions & 0 deletions dyngeneric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,23 @@ func TestArrayToString(t *testing.T) {
assert.Equal(t, "z,a,c,b", print)
assert.Equal(t, "z,a,c,b", defValue)
}

func TestRemoveCommon(t *testing.T) {
setA := NewSet("a", "b", "c", "d")
setB := NewSet("b", "d", "e", "f", "g")
setAA := setA.Clone()
setBB := setB.Clone()
RemoveCommon(setAA, setBB)
assert.Equal(t, "a,c", setAA.String()) // removed
assert.Equal(t, "e,f,g", setBB.String()) // added
// Swap order to exercise the optimization on length of iteration
// also check clone is not modifying the original etc
setAA = setB.Clone() // putting B in AA on purpose and vice versa
setBB = setA.Clone()
RemoveCommon(setAA, setBB)
assert.Equal(t, "a,c", setBB.String())
assert.Equal(t, "e,f,g", setAA.String())
assert.True(t, setBB.Has("c"))
setBB.Remove("c")
assert.False(t, setBB.Has("c"))
}

0 comments on commit 6641cac

Please sign in to comment.