1package sets
2
3import (
4 "iter"
5 "maps"
6)
7
8type Set[T comparable] struct {
9 data map[T]struct{}
10}
11
12func New[T comparable]() Set[T] {
13 return Set[T]{
14 data: make(map[T]struct{}),
15 }
16}
17
18func (s *Set[T]) Insert(item T) bool {
19 _, exists := s.data[item]
20 s.data[item] = struct{}{}
21 return !exists
22}
23
24func (s *Set[T]) Remove(item T) bool {
25 _, exists := s.data[item]
26 if exists {
27 delete(s.data, item)
28 }
29 return exists
30}
31
32func (s Set[T]) Contains(item T) bool {
33 _, exists := s.data[item]
34 return exists
35}
36
37func (s Set[T]) Len() int {
38 return len(s.data)
39}
40
41func (s Set[T]) IsEmpty() bool {
42 return len(s.data) == 0
43}
44
45func (s *Set[T]) Clear() {
46 s.data = make(map[T]struct{})
47}
48
49func (s Set[T]) All() iter.Seq[T] {
50 return func(yield func(T) bool) {
51 for item := range s.data {
52 if !yield(item) {
53 return
54 }
55 }
56 }
57}
58
59func (s Set[T]) Clone() Set[T] {
60 return Set[T]{
61 data: maps.Clone(s.data),
62 }
63}
64
65func (s Set[T]) Union(other Set[T]) iter.Seq[T] {
66 if s.Len() >= other.Len() {
67 return chain(s.All(), other.Difference(s))
68 } else {
69 return chain(other.All(), s.Difference(other))
70 }
71}
72
73func chain[T any](seqs ...iter.Seq[T]) iter.Seq[T] {
74 return func(yield func(T) bool) {
75 for _, seq := range seqs {
76 for item := range seq {
77 if !yield(item) {
78 return
79 }
80 }
81 }
82 }
83}
84
85func (s Set[T]) Intersection(other Set[T]) iter.Seq[T] {
86 return func(yield func(T) bool) {
87 for item := range s.data {
88 if other.Contains(item) {
89 if !yield(item) {
90 return
91 }
92 }
93 }
94 }
95}
96
97func (s Set[T]) Difference(other Set[T]) iter.Seq[T] {
98 return func(yield func(T) bool) {
99 for item := range s.data {
100 if !other.Contains(item) {
101 if !yield(item) {
102 return
103 }
104 }
105 }
106 }
107}
108
109func (s Set[T]) SymmetricDifference(other Set[T]) iter.Seq[T] {
110 return func(yield func(T) bool) {
111 for item := range s.data {
112 if !other.Contains(item) {
113 if !yield(item) {
114 return
115 }
116 }
117 }
118 for item := range other.data {
119 if !s.Contains(item) {
120 if !yield(item) {
121 return
122 }
123 }
124 }
125 }
126}
127
128func (s Set[T]) IsSubset(other Set[T]) bool {
129 for item := range s.data {
130 if !other.Contains(item) {
131 return false
132 }
133 }
134 return true
135}
136
137func (s Set[T]) IsSuperset(other Set[T]) bool {
138 return other.IsSubset(s)
139}
140
141func (s Set[T]) IsDisjoint(other Set[T]) bool {
142 for item := range s.data {
143 if other.Contains(item) {
144 return false
145 }
146 }
147 return true
148}
149
150func (s Set[T]) Equal(other Set[T]) bool {
151 if s.Len() != other.Len() {
152 return false
153 }
154 for item := range s.data {
155 if !other.Contains(item) {
156 return false
157 }
158 }
159 return true
160}
161
162func Collect[T comparable](seq iter.Seq[T]) Set[T] {
163 result := New[T]()
164 for item := range seq {
165 result.Insert(item)
166 }
167 return result
168}