Skip to content

Commit 13f8b1d

Browse files
add Append() method for adding multiple elements to set (#93)
* add Append() method for adding multiple elements to set * Fixing how Append gets dereferenced due to some recent changes. We no longer need two layers of indirection. --------- Co-authored-by: Ralph Caraveo <[email protected]>
1 parent 3045cfb commit 13f8b1d

File tree

6 files changed

+101
-5
lines changed

6 files changed

+101
-5
lines changed

iterator_example_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ type yourType struct {
3535

3636
func Test_ExampleIterator(t *testing.T) {
3737

38-
s := NewSet[*yourType](
38+
s := NewSet(
3939
[]*yourType{
40-
&yourType{name: "Alise"},
41-
&yourType{name: "Bob"},
42-
&yourType{name: "John"},
43-
&yourType{name: "Nick"},
40+
{name: "Alise"},
41+
{name: "Bob"},
42+
{name: "John"},
43+
{name: "Nick"},
4444
}...,
4545
)
4646

set.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ type Set[T comparable] interface {
4343
// the item was added.
4444
Add(val T) bool
4545

46+
// Append multiple elements to the set. Returns
47+
// the number of elements added.
48+
Append(val ...T) int
49+
4650
// Cardinality returns the number of elements in the set.
4751
Cardinality() int
4852

set_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ func makeUnsafeSetInt(ints []int) Set[int] {
4545
return s
4646
}
4747

48+
func makeSetIntWithAppend(ints ...int) Set[int] {
49+
s := NewSet[int]()
50+
s.Append(ints...)
51+
return s
52+
}
53+
54+
func makeUnsafeSetIntWithAppend(ints ...int) Set[int] {
55+
s := NewThreadUnsafeSet[int]()
56+
s.Append(ints...)
57+
return s
58+
}
59+
4860
func assertEqual[T comparable](a, b Set[T], t *testing.T) {
4961
if !a.Equal(b) {
5062
t.Errorf("%v != %v\n", a, b)
@@ -88,6 +100,22 @@ func Test_AddUnsafeSet(t *testing.T) {
88100
}
89101
}
90102

103+
func Test_AppendSet(t *testing.T) {
104+
a := makeSetIntWithAppend(1, 2, 3)
105+
106+
if a.Cardinality() != 3 {
107+
t.Error("AppendSet does not have a size of 3 even though 3 items were added to a new set")
108+
}
109+
}
110+
111+
func Test_AppendUnsafeSet(t *testing.T) {
112+
a := makeUnsafeSetIntWithAppend(1, 2, 3)
113+
114+
if a.Cardinality() != 3 {
115+
t.Error("AppendSet does not have a size of 3 even though 3 items were added to a new set")
116+
}
117+
}
118+
91119
func Test_AddSetNoDuplicate(t *testing.T) {
92120
a := makeSetInt([]int{7, 5, 3, 7})
93121

@@ -112,6 +140,30 @@ func Test_AddUnsafeSetNoDuplicate(t *testing.T) {
112140
}
113141
}
114142

143+
func Test_AppendSetNoDuplicate(t *testing.T) {
144+
a := makeSetIntWithAppend(7, 5, 3, 7)
145+
146+
if a.Cardinality() != 3 {
147+
t.Error("AppendSetNoDuplicate set should have 3 elements since 7 is a duplicate")
148+
}
149+
150+
if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) {
151+
t.Error("AppendSetNoDuplicate set should have a 7, 5, and 3 in it.")
152+
}
153+
}
154+
155+
func Test_AppendUnsafeSetNoDuplicate(t *testing.T) {
156+
a := makeUnsafeSetIntWithAppend(7, 5, 3, 7)
157+
158+
if a.Cardinality() != 3 {
159+
t.Error("AppendSetNoDuplicate set should have 3 elements since 7 is a duplicate")
160+
}
161+
162+
if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) {
163+
t.Error("AppendSetNoDuplicate set should have a 7, 5, and 3 in it.")
164+
}
165+
}
166+
115167
func Test_RemoveSet(t *testing.T) {
116168
a := makeSetInt([]int{6, 3, 1})
117169

threadsafe.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,18 @@ func (t *threadSafeSet[T]) Add(v T) bool {
4545
return ret
4646
}
4747

48+
func (t *threadSafeSet[T]) Append(v ...T) int {
49+
t.Lock()
50+
ret := t.uss.Append(v...)
51+
t.Unlock()
52+
return ret
53+
}
54+
4855
func (t *threadSafeSet[T]) Contains(v ...T) bool {
4956
t.RLock()
5057
ret := t.uss.Contains(v...)
5158
t.RUnlock()
59+
5260
return ret
5361
}
5462

threadsafe_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,30 @@ func Test_AddConcurrent(t *testing.T) {
5959
}
6060
}
6161

62+
func Test_AppendConcurrent(t *testing.T) {
63+
runtime.GOMAXPROCS(2)
64+
65+
s := NewSet[int]()
66+
ints := rand.Perm(N)
67+
68+
n := len(ints) >> 1
69+
var wg sync.WaitGroup
70+
wg.Add(n)
71+
for i := 0; i < n; i++ {
72+
go func(i int) {
73+
s.Append(i, N-i-1)
74+
wg.Done()
75+
}(i)
76+
}
77+
78+
wg.Wait()
79+
for _, i := range ints {
80+
if !s.Contains(i) {
81+
t.Errorf("Set is missing element: %v", i)
82+
}
83+
}
84+
}
85+
6286
func Test_CardinalityConcurrent(t *testing.T) {
6387
runtime.GOMAXPROCS(2)
6488

threadunsafe.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ func (s threadUnsafeSet[T]) Add(v T) bool {
4747
return prevLen != len(s)
4848
}
4949

50+
func (s threadUnsafeSet[T]) Append(v ...T) int {
51+
prevLen := len(s)
52+
for _, val := range v {
53+
(s)[val] = struct{}{}
54+
}
55+
return len(s) - prevLen
56+
}
57+
5058
// private version of Add which doesn't return a value
5159
func (s threadUnsafeSet[T]) add(v T) {
5260
s[v] = struct{}{}

0 commit comments

Comments
 (0)