a rusty set datastructure for go
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}