-
Notifications
You must be signed in to change notification settings - Fork 3
/
set.go
125 lines (111 loc) · 3.14 KB
/
set.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package set
// Set implements a unique, unordered set of homogeneous element types.
// An empty struct is used for the value, to signify that only its presence matters, not its value.
type Set[T comparable] map[T]struct{}
// FromSlice creates and returns a new Set using the supplied values and their type.
func FromSlice[T comparable](values []T) Set[T] {
set := make(Set[T], len(values))
set.Add(values...)
return set
}
// Add inserts a value to the set, without retaining insertion order.
func (s Set[T]) Add(values ...T) {
for _, value := range values {
s[value] = struct{}{}
}
}
// Delete removes all matching elements from the set.
func (s Set[T]) Delete(values ...T) {
for _, value := range values {
delete(s, value)
}
}
// Has returns a boolean, for whether the value exists in the Set.
func (s Set[T]) Has(value T) bool {
_, ok := s[value]
return ok
}
// Len returns the number of items in the Set.
func (s Set[T]) Len() int {
return len(s)
}
// ForEach accepts and applies a callback function to each element in the Set.
func (s Set[T]) ForEach(it func(T)) {
for value := range s {
it(value)
}
}
// Values returns all elements of the set, unordered.
func (s Set[T]) Values() []T {
values := make([]T, 0, s.Len())
s.ForEach(
func(value T) {
values = append(values, value)
},
)
return values
}
// Clone returns a new copy of the original Set.
func (s Set[T]) Clone() Set[T] {
set := make(Set[T])
set.Add(s.Values()...)
return set
}
// Union returns a Set of the combined Sets.
// Example: [1, 2].Union([2, 3]) = [1, 2, 3].
func (s Set[T]) Union(other Set[T]) Set[T] {
union := s.Clone()
union.Add(other.Values()...)
return union
}
// Intersection returns a Set containing all the common items between both Sets.
// Example: [1, 2, 3].Intersection([2, 3, 4]) = [2, 3].
func (s Set[T]) Intersection(other Set[T]) Set[T] {
intersection := make(Set[T])
s.ForEach(
func(value T) {
if other.Has(value) {
intersection.Add(value)
}
},
)
return intersection
}
// Difference returns a Set containing all the items not contained in the other set.
// Note this is "unidirectional", and the result is _only_ the elements in A that are not in B.
// Example: [1, 2, 3].Difference([2, 3, 4]) = [1].
func (s Set[T]) Difference(other Set[T]) Set[T] {
diff := make(Set[T])
s.ForEach(
func(value T) {
if !other.Has(value) {
diff.Add(value)
}
},
)
return diff
}
// SymmetricalDifference returns the inverse of Intersection, a Set containing all elements
// not common to both incoming Sets.
// Example: [1, 2, 3].SymmetricalDifference([2, 3, 4]) = [1, 4].
func (s Set[T]) SymmetricalDifference(other Set[T]) Set[T] {
// [1, 2, 3].Intersection([2, 3, 4]) = [2, 3]
intersection := s.Intersection(other)
// [1, 2, 3].Union([2, 3, 4]) = [1, 2, 3, 4]
union := s.Union(other)
// [1, 2, 3, 4].Difference([2, 3]) = [1, 4]
symmetricalDifference := union.Difference(intersection)
return symmetricalDifference
}
// Equals whether the sets have exactly the same elements.
func (s Set[T]) Equals(other Set[T]) bool {
if s.Len() != other.Len() {
return false
}
for value := range s {
if !other.Has(value) {
return false
}
}
return true
}