Skip to content

Commit d8088cf

Browse files
author
Han Kang
committed
add generic sets package to utils
1 parent d93618c commit d8088cf

File tree

3 files changed

+483
-0
lines changed

3 files changed

+483
-0
lines changed

sets/OWNERS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# See the OWNERS docs at https://go.k8s.io/owners
2+
3+
reviewers:
4+
- logicalhan
5+
- thockin
6+
- lavalamp
7+
approvers:
8+
- logicalhan
9+
- thockin
10+
- lavalamp

sets/set.go

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package sets
18+
19+
import "sort"
20+
21+
type Ordered interface {
22+
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64 | string
23+
}
24+
25+
// Empty is public since it is used by some internal API objects for conversions between external
26+
// string arrays and internal sets, and conversion logic requires public types today.
27+
type Empty struct{}
28+
29+
type Set[E Ordered] map[E]Empty
30+
31+
// NewSet creates a new set.
32+
func NewSet[E Ordered](items ...E) Set[E] {
33+
ss := Set[E]{}
34+
ss.Insert(items...)
35+
return ss
36+
}
37+
38+
// NewSetFromMapKeys creates a Set[E] from a keys of a map[E](? extends interface{}).
39+
func NewSetFromMapKeys[E Ordered, A any](theMap map[E]A) Set[E] {
40+
ret := Set[E]{}
41+
for key := range theMap {
42+
ret.Insert(key)
43+
}
44+
return ret
45+
}
46+
47+
// Insert adds items to the set.
48+
func (s Set[E]) Insert(items ...E) Set[E] {
49+
for _, item := range items {
50+
s[item] = Empty{}
51+
}
52+
return s
53+
}
54+
55+
// Delete removes all items from the set.
56+
func (s Set[E]) Delete(items ...E) Set[E] {
57+
for _, item := range items {
58+
delete(s, item)
59+
}
60+
return s
61+
}
62+
63+
// Has returns true if and only if item is contained in the set.
64+
func (s Set[E]) Has(item E) bool {
65+
_, contained := s[item]
66+
return contained
67+
}
68+
69+
// HasAll returns true if and only if all items are contained in the set.
70+
func (s Set[E]) HasAll(items ...E) bool {
71+
for _, item := range items {
72+
if !s.Has(item) {
73+
return false
74+
}
75+
}
76+
return true
77+
}
78+
79+
// HasAny returns true if any items are contained in the set.
80+
func (s Set[E]) HasAny(items ...E) bool {
81+
for _, item := range items {
82+
if s.Has(item) {
83+
return true
84+
}
85+
}
86+
return false
87+
}
88+
89+
func (s Set[E]) Union(s2 Set[E]) Set[E] {
90+
result := Set[E]{}
91+
result.Insert(s.List()...)
92+
result.Insert(s2.List()...)
93+
return result
94+
}
95+
96+
// Len returns the size of the set.
97+
func (s Set[E]) Len() int {
98+
return len(s)
99+
}
100+
101+
func (s Set[E]) Intersection(s2 Set[E]) Set[E] {
102+
var walk, other Set[E]
103+
result := Set[E]{}
104+
if s.Len() < s2.Len() {
105+
walk = s
106+
other = s2
107+
} else {
108+
walk = s2
109+
other = s
110+
}
111+
for key := range walk {
112+
if other.Has(key) {
113+
result.Insert(key)
114+
}
115+
}
116+
return result
117+
}
118+
119+
// IsSuperset returns true if and only if s1 is a superset of s2.
120+
func (s Set[E]) IsSuperset(s2 Set[E]) bool {
121+
for item := range s2 {
122+
if !s.Has(item) {
123+
return false
124+
}
125+
}
126+
return true
127+
}
128+
129+
// Difference returns a set of objects that are not in s2
130+
// For example:
131+
// s1 = {a1, a2, a3}
132+
// s2 = {a1, a2, a4, a5}
133+
// s1.Difference(s2) = {a3}
134+
// s2.Difference(s1) = {a4, a5}
135+
func (s Set[E]) Difference(s2 Set[E]) Set[E] {
136+
result := Set[E]{}
137+
for key := range s {
138+
if !s2.Has(key) {
139+
result.Insert(key)
140+
}
141+
}
142+
return result
143+
}
144+
145+
// Equal returns true if and only if s1 is equal (as a set) to s2.
146+
// Two sets are equal if their membership is identical.
147+
// (In practice, this means same elements, order doesn't matter)
148+
func (s Set[E]) Equal(s2 Set[E]) bool {
149+
return s.Len() == s.Len() && s.IsSuperset(s2)
150+
}
151+
152+
type sortableSlice[E Ordered] []E
153+
154+
func (s sortableSlice[E]) Len() int {
155+
return len(s)
156+
}
157+
func (s sortableSlice[E]) Less(i, j int) bool { return s[i] < s[j] }
158+
func (s sortableSlice[E]) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
159+
160+
// List returns the contents as a sorted int slice.
161+
func (s Set[E]) List() []E {
162+
res := make(sortableSlice[E], 0, s.Len())
163+
for key := range s {
164+
res = append(res, key)
165+
}
166+
sort.Sort(res)
167+
return res
168+
}
169+
170+
// UnsortedList returns the slice with contents in random order.
171+
func (s Set[E]) UnsortedList() []E {
172+
res := make(sortableSlice[E], 0, len(s))
173+
for key := range s {
174+
res = append(res, key)
175+
}
176+
return res
177+
}
178+
179+
// PopAny returns a single element from the set.
180+
func (s Set[E]) PopAny() (E, bool) {
181+
for key := range s {
182+
s.Delete(key)
183+
return key, true
184+
}
185+
var zeroValue E
186+
return zeroValue, false
187+
}

0 commit comments

Comments
 (0)