k8s.io/apimachinery@v0.29.2/pkg/util/sets/set.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package sets
    18  
    19  import (
    20  	"sort"
    21  )
    22  
    23  // Set is a set of the same type elements, implemented via map[comparable]struct{} for minimal memory consumption.
    24  type Set[T comparable] map[T]Empty
    25  
    26  // cast transforms specified set to generic Set[T].
    27  func cast[T comparable](s map[T]Empty) Set[T] { return s }
    28  
    29  // New creates a Set from a list of values.
    30  // NOTE: type param must be explicitly instantiated if given items are empty.
    31  func New[T comparable](items ...T) Set[T] {
    32  	ss := make(Set[T], len(items))
    33  	ss.Insert(items...)
    34  	return ss
    35  }
    36  
    37  // KeySet creates a Set from a keys of a map[comparable](? extends interface{}).
    38  // If the value passed in is not actually a map, this will panic.
    39  func KeySet[T comparable, V any](theMap map[T]V) Set[T] {
    40  	ret := Set[T]{}
    41  	for keyValue := range theMap {
    42  		ret.Insert(keyValue)
    43  	}
    44  	return ret
    45  }
    46  
    47  // Insert adds items to the set.
    48  func (s Set[T]) Insert(items ...T) Set[T] {
    49  	for _, item := range items {
    50  		s[item] = Empty{}
    51  	}
    52  	return s
    53  }
    54  
    55  func Insert[T comparable](set Set[T], items ...T) Set[T] {
    56  	return set.Insert(items...)
    57  }
    58  
    59  // Delete removes all items from the set.
    60  func (s Set[T]) Delete(items ...T) Set[T] {
    61  	for _, item := range items {
    62  		delete(s, item)
    63  	}
    64  	return s
    65  }
    66  
    67  // Clear empties the set.
    68  // It is preferable to replace the set with a newly constructed set,
    69  // but not all callers can do that (when there are other references to the map).
    70  // In some cases the set *won't* be fully cleared, e.g. a Set[float32] containing NaN
    71  // can't be cleared because NaN can't be removed.
    72  // For sets containing items of a type that is reflexive for ==,
    73  // this is optimized to a single call to runtime.mapclear().
    74  func (s Set[T]) Clear() Set[T] {
    75  	for key := range s {
    76  		delete(s, key)
    77  	}
    78  	return s
    79  }
    80  
    81  // Has returns true if and only if item is contained in the set.
    82  func (s Set[T]) Has(item T) bool {
    83  	_, contained := s[item]
    84  	return contained
    85  }
    86  
    87  // HasAll returns true if and only if all items are contained in the set.
    88  func (s Set[T]) HasAll(items ...T) bool {
    89  	for _, item := range items {
    90  		if !s.Has(item) {
    91  			return false
    92  		}
    93  	}
    94  	return true
    95  }
    96  
    97  // HasAny returns true if any items are contained in the set.
    98  func (s Set[T]) HasAny(items ...T) bool {
    99  	for _, item := range items {
   100  		if s.Has(item) {
   101  			return true
   102  		}
   103  	}
   104  	return false
   105  }
   106  
   107  // Clone returns a new set which is a copy of the current set.
   108  func (s Set[T]) Clone() Set[T] {
   109  	result := make(Set[T], len(s))
   110  	for key := range s {
   111  		result.Insert(key)
   112  	}
   113  	return result
   114  }
   115  
   116  // Difference returns a set of objects that are not in s2.
   117  // For example:
   118  // s1 = {a1, a2, a3}
   119  // s2 = {a1, a2, a4, a5}
   120  // s1.Difference(s2) = {a3}
   121  // s2.Difference(s1) = {a4, a5}
   122  func (s1 Set[T]) Difference(s2 Set[T]) Set[T] {
   123  	result := New[T]()
   124  	for key := range s1 {
   125  		if !s2.Has(key) {
   126  			result.Insert(key)
   127  		}
   128  	}
   129  	return result
   130  }
   131  
   132  // SymmetricDifference returns a set of elements which are in either of the sets, but not in their intersection.
   133  // For example:
   134  // s1 = {a1, a2, a3}
   135  // s2 = {a1, a2, a4, a5}
   136  // s1.SymmetricDifference(s2) = {a3, a4, a5}
   137  // s2.SymmetricDifference(s1) = {a3, a4, a5}
   138  func (s1 Set[T]) SymmetricDifference(s2 Set[T]) Set[T] {
   139  	return s1.Difference(s2).Union(s2.Difference(s1))
   140  }
   141  
   142  // Union returns a new set which includes items in either s1 or s2.
   143  // For example:
   144  // s1 = {a1, a2}
   145  // s2 = {a3, a4}
   146  // s1.Union(s2) = {a1, a2, a3, a4}
   147  // s2.Union(s1) = {a1, a2, a3, a4}
   148  func (s1 Set[T]) Union(s2 Set[T]) Set[T] {
   149  	result := s1.Clone()
   150  	for key := range s2 {
   151  		result.Insert(key)
   152  	}
   153  	return result
   154  }
   155  
   156  // Intersection returns a new set which includes the item in BOTH s1 and s2
   157  // For example:
   158  // s1 = {a1, a2}
   159  // s2 = {a2, a3}
   160  // s1.Intersection(s2) = {a2}
   161  func (s1 Set[T]) Intersection(s2 Set[T]) Set[T] {
   162  	var walk, other Set[T]
   163  	result := New[T]()
   164  	if s1.Len() < s2.Len() {
   165  		walk = s1
   166  		other = s2
   167  	} else {
   168  		walk = s2
   169  		other = s1
   170  	}
   171  	for key := range walk {
   172  		if other.Has(key) {
   173  			result.Insert(key)
   174  		}
   175  	}
   176  	return result
   177  }
   178  
   179  // IsSuperset returns true if and only if s1 is a superset of s2.
   180  func (s1 Set[T]) IsSuperset(s2 Set[T]) bool {
   181  	for item := range s2 {
   182  		if !s1.Has(item) {
   183  			return false
   184  		}
   185  	}
   186  	return true
   187  }
   188  
   189  // Equal returns true if and only if s1 is equal (as a set) to s2.
   190  // Two sets are equal if their membership is identical.
   191  // (In practice, this means same elements, order doesn't matter)
   192  func (s1 Set[T]) Equal(s2 Set[T]) bool {
   193  	return len(s1) == len(s2) && s1.IsSuperset(s2)
   194  }
   195  
   196  type sortableSliceOfGeneric[T ordered] []T
   197  
   198  func (g sortableSliceOfGeneric[T]) Len() int           { return len(g) }
   199  func (g sortableSliceOfGeneric[T]) Less(i, j int) bool { return less[T](g[i], g[j]) }
   200  func (g sortableSliceOfGeneric[T]) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
   201  
   202  // List returns the contents as a sorted T slice.
   203  //
   204  // This is a separate function and not a method because not all types supported
   205  // by Generic are ordered and only those can be sorted.
   206  func List[T ordered](s Set[T]) []T {
   207  	res := make(sortableSliceOfGeneric[T], 0, len(s))
   208  	for key := range s {
   209  		res = append(res, key)
   210  	}
   211  	sort.Sort(res)
   212  	return res
   213  }
   214  
   215  // UnsortedList returns the slice with contents in random order.
   216  func (s Set[T]) UnsortedList() []T {
   217  	res := make([]T, 0, len(s))
   218  	for key := range s {
   219  		res = append(res, key)
   220  	}
   221  	return res
   222  }
   223  
   224  // PopAny returns a single element from the set.
   225  func (s Set[T]) PopAny() (T, bool) {
   226  	for key := range s {
   227  		s.Delete(key)
   228  		return key, true
   229  	}
   230  	var zeroValue T
   231  	return zeroValue, false
   232  }
   233  
   234  // Len returns the size of the set.
   235  func (s Set[T]) Len() int {
   236  	return len(s)
   237  }
   238  
   239  func less[T ordered](lhs, rhs T) bool {
   240  	return lhs < rhs
   241  }