github.com/lingyao2333/mo-zero@v1.4.1/core/collection/set.go (about) 1 package collection 2 3 import ( 4 "github.com/lingyao2333/mo-zero/core/lang" 5 "github.com/lingyao2333/mo-zero/core/logx" 6 ) 7 8 const ( 9 unmanaged = iota 10 untyped 11 intType 12 int64Type 13 uintType 14 uint64Type 15 stringType 16 ) 17 18 // Set is not thread-safe, for concurrent use, make sure to use it with synchronization. 19 type Set struct { 20 data map[interface{}]lang.PlaceholderType 21 tp int 22 } 23 24 // NewSet returns a managed Set, can only put the values with the same type. 25 func NewSet() *Set { 26 return &Set{ 27 data: make(map[interface{}]lang.PlaceholderType), 28 tp: untyped, 29 } 30 } 31 32 // NewUnmanagedSet returns an unmanaged Set, which can put values with different types. 33 func NewUnmanagedSet() *Set { 34 return &Set{ 35 data: make(map[interface{}]lang.PlaceholderType), 36 tp: unmanaged, 37 } 38 } 39 40 // Add adds i into s. 41 func (s *Set) Add(i ...interface{}) { 42 for _, each := range i { 43 s.add(each) 44 } 45 } 46 47 // AddInt adds int values ii into s. 48 func (s *Set) AddInt(ii ...int) { 49 for _, each := range ii { 50 s.add(each) 51 } 52 } 53 54 // AddInt64 adds int64 values ii into s. 55 func (s *Set) AddInt64(ii ...int64) { 56 for _, each := range ii { 57 s.add(each) 58 } 59 } 60 61 // AddUint adds uint values ii into s. 62 func (s *Set) AddUint(ii ...uint) { 63 for _, each := range ii { 64 s.add(each) 65 } 66 } 67 68 // AddUint64 adds uint64 values ii into s. 69 func (s *Set) AddUint64(ii ...uint64) { 70 for _, each := range ii { 71 s.add(each) 72 } 73 } 74 75 // AddStr adds string values ss into s. 76 func (s *Set) AddStr(ss ...string) { 77 for _, each := range ss { 78 s.add(each) 79 } 80 } 81 82 // Contains checks if i is in s. 83 func (s *Set) Contains(i interface{}) bool { 84 if len(s.data) == 0 { 85 return false 86 } 87 88 s.validate(i) 89 _, ok := s.data[i] 90 return ok 91 } 92 93 // Keys returns the keys in s. 94 func (s *Set) Keys() []interface{} { 95 var keys []interface{} 96 97 for key := range s.data { 98 keys = append(keys, key) 99 } 100 101 return keys 102 } 103 104 // KeysInt returns the int keys in s. 105 func (s *Set) KeysInt() []int { 106 var keys []int 107 108 for key := range s.data { 109 if intKey, ok := key.(int); ok { 110 keys = append(keys, intKey) 111 } 112 } 113 114 return keys 115 } 116 117 // KeysInt64 returns int64 keys in s. 118 func (s *Set) KeysInt64() []int64 { 119 var keys []int64 120 121 for key := range s.data { 122 if intKey, ok := key.(int64); ok { 123 keys = append(keys, intKey) 124 } 125 } 126 127 return keys 128 } 129 130 // KeysUint returns uint keys in s. 131 func (s *Set) KeysUint() []uint { 132 var keys []uint 133 134 for key := range s.data { 135 if intKey, ok := key.(uint); ok { 136 keys = append(keys, intKey) 137 } 138 } 139 140 return keys 141 } 142 143 // KeysUint64 returns uint64 keys in s. 144 func (s *Set) KeysUint64() []uint64 { 145 var keys []uint64 146 147 for key := range s.data { 148 if intKey, ok := key.(uint64); ok { 149 keys = append(keys, intKey) 150 } 151 } 152 153 return keys 154 } 155 156 // KeysStr returns string keys in s. 157 func (s *Set) KeysStr() []string { 158 var keys []string 159 160 for key := range s.data { 161 if strKey, ok := key.(string); ok { 162 keys = append(keys, strKey) 163 } 164 } 165 166 return keys 167 } 168 169 // Remove removes i from s. 170 func (s *Set) Remove(i interface{}) { 171 s.validate(i) 172 delete(s.data, i) 173 } 174 175 // Count returns the number of items in s. 176 func (s *Set) Count() int { 177 return len(s.data) 178 } 179 180 func (s *Set) add(i interface{}) { 181 switch s.tp { 182 case unmanaged: 183 // do nothing 184 case untyped: 185 s.setType(i) 186 default: 187 s.validate(i) 188 } 189 s.data[i] = lang.Placeholder 190 } 191 192 func (s *Set) setType(i interface{}) { 193 // s.tp can only be untyped here 194 switch i.(type) { 195 case int: 196 s.tp = intType 197 case int64: 198 s.tp = int64Type 199 case uint: 200 s.tp = uintType 201 case uint64: 202 s.tp = uint64Type 203 case string: 204 s.tp = stringType 205 } 206 } 207 208 func (s *Set) validate(i interface{}) { 209 if s.tp == unmanaged { 210 return 211 } 212 213 switch i.(type) { 214 case int: 215 if s.tp != intType { 216 logx.Errorf("Error: element is int, but set contains elements with type %d", s.tp) 217 } 218 case int64: 219 if s.tp != int64Type { 220 logx.Errorf("Error: element is int64, but set contains elements with type %d", s.tp) 221 } 222 case uint: 223 if s.tp != uintType { 224 logx.Errorf("Error: element is uint, but set contains elements with type %d", s.tp) 225 } 226 case uint64: 227 if s.tp != uint64Type { 228 logx.Errorf("Error: element is uint64, but set contains elements with type %d", s.tp) 229 } 230 case string: 231 if s.tp != stringType { 232 logx.Errorf("Error: element is string, but set contains elements with type %d", s.tp) 233 } 234 } 235 }