go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/data/stringset/stringset.go (about) 1 // Copyright 2015 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package stringset 16 17 import "sort" 18 19 // Set is the base type. make(Set) can be used too. 20 type Set map[string]struct{} 21 22 // New returns a new string Set implementation. 23 func New(sizeHint int) Set { 24 return make(Set, sizeHint) 25 } 26 27 // NewFromSlice returns a new string Set implementation, 28 // initialized with the values in the provided slice. 29 func NewFromSlice(vals ...string) Set { 30 ret := make(Set, len(vals)) 31 for _, k := range vals { 32 ret[k] = struct{}{} 33 } 34 return ret 35 } 36 37 // Has returns true iff the Set contains value. 38 func (s Set) Has(value string) bool { 39 _, ret := s[value] 40 return ret 41 } 42 43 // HasAll returns true iff the Set contains all the given values. 44 func (s Set) HasAll(values ...string) bool { 45 for _, v := range values { 46 if !s.Has(v) { 47 return false 48 } 49 } 50 return true 51 } 52 53 // Add ensures that Set contains value, and returns true if it was added (i.e. 54 // it returns false if the Set already contained the value). 55 func (s Set) Add(value string) bool { 56 if _, ok := s[value]; ok { 57 return false 58 } 59 s[value] = struct{}{} 60 return true 61 } 62 63 // AddAll ensures that Set contains all values. 64 func (s Set) AddAll(values []string) { 65 for _, value := range values { 66 s[value] = struct{}{} 67 } 68 } 69 70 // Del removes value from the set, and returns true if it was deleted (i.e. it 71 // returns false if the Set did not already contain the value). 72 func (s Set) Del(value string) bool { 73 if _, ok := s[value]; !ok { 74 return false 75 } 76 delete(s, value) 77 return true 78 } 79 80 // DelAll ensures that Set contains none of values. 81 func (s Set) DelAll(values []string) { 82 for _, value := range values { 83 delete(s, value) 84 } 85 } 86 87 // Peek returns an arbitrary element from the set. If the set was empty, this 88 // returns ("", false). 89 func (s Set) Peek() (string, bool) { 90 for k := range s { 91 return k, true 92 } 93 return "", false 94 } 95 96 // Pop removes and returns an arbitrary element from the set and removes it from the 97 // set. If the set was empty, this returns ("", false). 98 func (s Set) Pop() (string, bool) { 99 for k := range s { 100 delete(s, k) 101 return k, true 102 } 103 return "", false 104 } 105 106 // Iter calls `cb` for each item in the set. If `cb` returns false, the 107 // iteration stops. 108 func (s Set) Iter(cb func(string) bool) { 109 for k := range s { 110 if !cb(k) { 111 break 112 } 113 } 114 } 115 116 // Len returns the number of items in this set. 117 func (s Set) Len() int { 118 return len(s) 119 } 120 121 // Dup returns a duplicate set. 122 func (s Set) Dup() Set { 123 ret := make(Set, len(s)) 124 for k := range s { 125 ret[k] = struct{}{} 126 } 127 return ret 128 } 129 130 // ToSlice renders this set to a slice of all values. 131 func (s Set) ToSlice() []string { 132 ret := make([]string, 0, len(s)) 133 for k := range s { 134 ret = append(ret, k) 135 } 136 return ret 137 } 138 139 // ToSortedSlice renders this set to a sorted slice of all values, ascending. 140 func (s Set) ToSortedSlice() []string { 141 ret := s.ToSlice() 142 sort.Strings(ret) 143 return ret 144 } 145 146 // Intersect returns a new Set which is the intersection of this set with the 147 // other set. 148 func (s Set) Intersect(other Set) Set { 149 smallLen := len(s) 150 if lo := len(other); lo < smallLen { 151 smallLen = lo 152 } 153 ret := make(Set, smallLen) 154 for k := range s { 155 if _, ok := other[k]; ok { 156 ret[k] = struct{}{} 157 } 158 } 159 return ret 160 } 161 162 // Difference returns a new Set which is this set with all elements from other 163 // removed (i.e. `self - other`). 164 func (s Set) Difference(other Set) Set { 165 ret := make(Set) 166 for k := range s { 167 if _, ok := other[k]; !ok { 168 ret[k] = struct{}{} 169 } 170 } 171 return ret 172 } 173 174 // Union returns a new Set which contains all element from this set, as well 175 // as all elements from the other set. 176 func (s Set) Union(other Set) Set { 177 ret := make(Set, len(s)) 178 for k := range s { 179 ret[k] = struct{}{} 180 } 181 for k := range other { 182 ret[k] = struct{}{} 183 } 184 return ret 185 } 186 187 // Contains returns true iff the given set contains all elements from the other set. 188 func (s Set) Contains(other Set) bool { 189 for k := range other { 190 if !s.Has(k) { 191 return false 192 } 193 } 194 return true 195 }