github.com/kaydxh/golang@v0.0.131/go/container/set/set_string.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package set 23 24 import ( 25 "reflect" 26 "sort" 27 ) 28 29 type Empty struct{} 30 31 // sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption. 32 type String map[string]Empty 33 34 // NewString creates a String from a list of values. 35 func NewString(items ...string) String { 36 ss := String{} 37 ss.Insert(items...) 38 return ss 39 } 40 41 // StringKeySet creates a String from a keys of a map[string](? extends interface{}). 42 // If the value passed in is not actually a map, this will panic. 43 func StringKeySet(theMap interface{}) String { 44 v := reflect.ValueOf(theMap) 45 ret := String{} 46 47 for _, keyValue := range v.MapKeys() { 48 ret.Insert(keyValue.Interface().(string)) 49 } 50 return ret 51 } 52 53 // Insert adds items to the set. 54 func (s String) Insert(items ...string) String { 55 for _, item := range items { 56 s[item] = Empty{} 57 } 58 return s 59 } 60 61 // Delete removes all items from the set. 62 func (s String) Delete(items ...string) String { 63 for _, item := range items { 64 delete(s, item) 65 } 66 return s 67 } 68 69 // Has returns true if and only if item is contained in the set. 70 func (s String) Has(item string) bool { 71 _, contained := s[item] 72 return contained 73 } 74 75 // HasAll returns true if and only if all items are contained in the set. 76 func (s String) HasAll(items ...string) bool { 77 for _, item := range items { 78 if !s.Has(item) { 79 return false 80 } 81 } 82 return true 83 } 84 85 // HasAny returns true if any items are contained in the set. 86 func (s String) HasAny(items ...string) bool { 87 for _, item := range items { 88 if s.Has(item) { 89 return true 90 } 91 } 92 return false 93 } 94 95 // Difference returns a set of objects that are not in s2 96 // For example: 97 // s1 = {a1, a2, a3} 98 // s2 = {a1, a2, a4, a5} 99 // s1.Difference(s2) = {a3} 100 // s2.Difference(s1) = {a4, a5} 101 func (s String) Difference(s2 String) String { 102 result := NewString() 103 for key := range s { 104 if !s2.Has(key) { 105 result.Insert(key) 106 } 107 } 108 return result 109 } 110 111 // Union returns a new set which includes items in either s1 or s2. 112 // For example: 113 // s1 = {a1, a2} 114 // s2 = {a3, a4} 115 // s1.Union(s2) = {a1, a2, a3, a4} 116 // s2.Union(s1) = {a1, a2, a3, a4} 117 func (s1 String) Union(s2 String) String { 118 result := NewString() 119 for key := range s1 { 120 result.Insert(key) 121 } 122 for key := range s2 { 123 result.Insert(key) 124 } 125 return result 126 } 127 128 // Intersection returns a new set which includes the item in BOTH s1 and s2 129 // For example: 130 // s1 = {a1, a2} 131 // s2 = {a2, a3} 132 // s1.Intersection(s2) = {a2} 133 func (s1 String) Intersection(s2 String) String { 134 var walk, other String 135 result := NewString() 136 if s1.Len() < s2.Len() { 137 walk = s1 138 other = s2 139 } else { 140 walk = s2 141 other = s1 142 } 143 for key := range walk { 144 if other.Has(key) { 145 result.Insert(key) 146 } 147 } 148 return result 149 } 150 151 // IsSuperset returns true if and only if s1 is a superset of s2. 152 func (s1 String) IsSuperset(s2 String) bool { 153 for item := range s2 { 154 if !s1.Has(item) { 155 return false 156 } 157 } 158 return true 159 } 160 161 // Equal returns true if and only if s1 is equal (as a set) to s2. 162 // Two sets are equal if their membership is identical. 163 // (In practice, this means same elements, order doesn't matter) 164 func (s1 String) Equal(s2 String) bool { 165 return len(s1) == len(s2) && s1.IsSuperset(s2) 166 } 167 168 type sortableSliceOfString []string 169 170 func (s sortableSliceOfString) Len() int { return len(s) } 171 func (s sortableSliceOfString) Less(i, j int) bool { return lessString(s[i], s[j]) } 172 func (s sortableSliceOfString) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 173 174 // List returns the contents as a sorted string slice. 175 func (s String) List() []string { 176 res := make(sortableSliceOfString, 0, len(s)) 177 for key := range s { 178 res = append(res, key) 179 } 180 sort.Sort(res) 181 return []string(res) 182 } 183 184 // UnsortedList returns the slice with contents in random order. 185 func (s String) UnsortedList() []string { 186 res := make([]string, 0, len(s)) 187 for key := range s { 188 res = append(res, key) 189 } 190 return res 191 } 192 193 // Returns a single element from the set. 194 func (s String) PopAny() (string, bool) { 195 for key := range s { 196 s.Delete(key) 197 return key, true 198 } 199 var zeroValue string 200 return zeroValue, false 201 } 202 203 // Len returns the size of the set. 204 func (s String) Len() int { 205 return len(s) 206 } 207 208 func lessString(lhs, rhs string) bool { 209 return lhs < rhs 210 }