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