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  }