Skip to content

Commit e1dc81f

Browse files
authored
feat: add ContainsAnyElement method (#149)
1 parent 5227976 commit e1dc81f

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed

set.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ type Set[T comparable] interface {
7373
// given items are in the set.
7474
ContainsAny(val ...T) bool
7575

76+
// ContainsAnyElement returns whether at least one of the
77+
// given element are in the set.
78+
ContainsAnyElement(other Set[T]) bool
79+
7680
// Difference returns the difference between this set
7781
// and other. The returned set will contain
7882
// all elements of this set that are not also

set_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,33 @@ func Test_ContainsAnySet(t *testing.T) {
398398
}
399399
}
400400

401+
func Test_ContainsAnyElement(t *testing.T) {
402+
a := NewSet[int]()
403+
a.Add(1)
404+
a.Add(3)
405+
a.Add(5)
406+
407+
b := NewSet[int]()
408+
a.Add(2)
409+
a.Add(4)
410+
a.Add(6)
411+
412+
if ret := a.ContainsAnyElement(b); ret {
413+
t.Errorf("set a not contain any element in set b")
414+
}
415+
416+
a.Add(10)
417+
418+
if ret := a.ContainsAnyElement(b); ret {
419+
t.Errorf("set a not contain any element in set b")
420+
}
421+
422+
b.Add(10)
423+
424+
if ret := a.ContainsAnyElement(b); !ret {
425+
t.Errorf("set a contain 10")
426+
}
427+
}
401428
func Test_ClearSet(t *testing.T) {
402429
a := makeSetInt([]int{2, 5, 9, 10})
403430

threadsafe.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ func (t *threadSafeSet[T]) ContainsAny(v ...T) bool {
8282
return ret
8383
}
8484

85+
func (t *threadSafeSet[T]) ContainsAnyElement(other Set[T]) bool {
86+
o := other.(*threadSafeSet[T])
87+
88+
t.RLock()
89+
o.RLock()
90+
91+
ret := t.uss.ContainsAnyElement(o.uss)
92+
93+
t.RUnlock()
94+
o.RUnlock()
95+
return ret
96+
}
97+
8598
func (t *threadSafeSet[T]) IsEmpty() bool {
8699
return t.Cardinality() == 0
87100
}

threadsafe_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,27 @@ func Test_ContainsAnyConcurrent(t *testing.T) {
217217
wg.Wait()
218218
}
219219

220+
func Test_ContainsAnyElementConcurrent(t *testing.T) {
221+
runtime.GOMAXPROCS(2)
222+
223+
s, ss := NewSet[int](), NewSet[int]()
224+
ints := rand.Perm(N)
225+
for _, v := range ints {
226+
s.Add(v)
227+
ss.Add(v)
228+
}
229+
230+
var wg sync.WaitGroup
231+
for range ints {
232+
wg.Add(1)
233+
go func() {
234+
s.ContainsAnyElement(ss)
235+
wg.Done()
236+
}()
237+
}
238+
wg.Wait()
239+
}
240+
220241
func Test_DifferenceConcurrent(t *testing.T) {
221242
runtime.GOMAXPROCS(2)
222243

threadunsafe.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,26 @@ func (s *threadUnsafeSet[T]) ContainsAny(v ...T) bool {
109109
return false
110110
}
111111

112+
func (s *threadUnsafeSet[T]) ContainsAnyElement(other Set[T]) bool {
113+
o := other.(*threadUnsafeSet[T])
114+
115+
// loop over smaller set
116+
if s.Cardinality() < other.Cardinality() {
117+
for elem := range *s {
118+
if o.contains(elem) {
119+
return true
120+
}
121+
}
122+
} else {
123+
for elem := range *o {
124+
if s.contains(elem) {
125+
return true
126+
}
127+
}
128+
}
129+
return false
130+
}
131+
112132
// private version of Contains for a single element v
113133
func (s *threadUnsafeSet[T]) contains(v T) (ok bool) {
114134
_, ok = (*s)[v]

0 commit comments

Comments
 (0)