github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/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  // Has returns true if and only if item is contained in the set.
    68  func (s Set[T]) Has(item T) bool {
    69  	_, contained := s[item]
    70  	return contained
    71  }
    72  
    73  // HasAll returns true if and only if all items are contained in the set.
    74  func (s Set[T]) HasAll(items ...T) bool {
    75  	for _, item := range items {
    76  		if !s.Has(item) {
    77  			return false
    78  		}
    79  	}
    80  	return true
    81  }
    82  
    83  // HasAny returns true if any items are contained in the set.
    84  func (s Set[T]) HasAny(items ...T) bool {
    85  	for _, item := range items {
    86  		if s.Has(item) {
    87  			return true
    88  		}
    89  	}
    90  	return false
    91  }
    92  
    93  // Clone returns a new set which is a copy of the current set.
    94  func (s Set[T]) Clone() Set[T] {
    95  	result := make(Set[T], len(s))
    96  	for key := range s {
    97  		result.Insert(key)
    98  	}
    99  	return result
   100  }
   101  
   102  // Difference returns a set of objects that are not in s2.
   103  // For example:
   104  // s1 = {a1, a2, a3}
   105  // s2 = {a1, a2, a4, a5}
   106  // s1.Difference(s2) = {a3}
   107  // s2.Difference(s1) = {a4, a5}
   108  func (s1 Set[T]) Difference(s2 Set[T]) Set[T] {
   109  	result := New[T]()
   110  	for key := range s1 {
   111  		if !s2.Has(key) {
   112  			result.Insert(key)
   113  		}
   114  	}
   115  	return result
   116  }
   117  
   118  // SymmetricDifference returns a set of elements which are in either of the sets, but not in their intersection.
   119  // For example:
   120  // s1 = {a1, a2, a3}
   121  // s2 = {a1, a2, a4, a5}
   122  // s1.SymmetricDifference(s2) = {a3, a4, a5}
   123  // s2.SymmetricDifference(s1) = {a3, a4, a5}
   124  func (s1 Set[T]) SymmetricDifference(s2 Set[T]) Set[T] {
   125  	return s1.Difference(s2).Union(s2.Difference(s1))
   126  }
   127  
   128  // Union returns a new set which includes items in either s1 or s2.
   129  // For example:
   130  // s1 = {a1, a2}
   131  // s2 = {a3, a4}
   132  // s1.Union(s2) = {a1, a2, a3, a4}
   133  // s2.Union(s1) = {a1, a2, a3, a4}
   134  func (s1 Set[T]) Union(s2 Set[T]) Set[T] {
   135  	result := s1.Clone()
   136  	for key := range s2 {
   137  		result.Insert(key)
   138  	}
   139  	return result
   140  }
   141  
   142  // Intersection returns a new set which includes the item in BOTH s1 and s2
   143  // For example:
   144  // s1 = {a1, a2}
   145  // s2 = {a2, a3}
   146  // s1.Intersection(s2) = {a2}
   147  func (s1 Set[T]) Intersection(s2 Set[T]) Set[T] {
   148  	var walk, other Set[T]
   149  	result := New[T]()
   150  	if s1.Len() < s2.Len() {
   151  		walk = s1
   152  		other = s2
   153  	} else {
   154  		walk = s2
   155  		other = s1
   156  	}
   157  	for key := range walk {
   158  		if other.Has(key) {
   159  			result.Insert(key)
   160  		}
   161  	}
   162  	return result
   163  }
   164  
   165  // IsSuperset returns true if and only if s1 is a superset of s2.
   166  func (s1 Set[T]) IsSuperset(s2 Set[T]) bool {
   167  	for item := range s2 {
   168  		if !s1.Has(item) {
   169  			return false
   170  		}
   171  	}
   172  	return true
   173  }
   174  
   175  // Equal returns true if and only if s1 is equal (as a set) to s2.
   176  // Two sets are equal if their membership is identical.
   177  // (In practice, this means same elements, order doesn't matter)
   178  func (s1 Set[T]) Equal(s2 Set[T]) bool {
   179  	return len(s1) == len(s2) && s1.IsSuperset(s2)
   180  }
   181  
   182  type sortableSliceOfGeneric[T ordered] []T
   183  
   184  func (g sortableSliceOfGeneric[T]) Len() int           { return len(g) }
   185  func (g sortableSliceOfGeneric[T]) Less(i, j int) bool { return less[T](g[i], g[j]) }
   186  func (g sortableSliceOfGeneric[T]) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
   187  
   188  // List returns the contents as a sorted T slice.
   189  //
   190  // This is a separate function and not a method because not all types supported
   191  // by Generic are ordered and only those can be sorted.
   192  func List[T ordered](s Set[T]) []T {
   193  	res := make(sortableSliceOfGeneric[T], 0, len(s))
   194  	for key := range s {
   195  		res = append(res, key)
   196  	}
   197  	sort.Sort(res)
   198  	return res
   199  }
   200  
   201  // UnsortedList returns the slice with contents in random order.
   202  func (s Set[T]) UnsortedList() []T {
   203  	res := make([]T, 0, len(s))
   204  	for key := range s {
   205  		res = append(res, key)
   206  	}
   207  	return res
   208  }
   209  
   210  // PopAny returns a single element from the set.
   211  func (s Set[T]) PopAny() (T, bool) {
   212  	for key := range s {
   213  		s.Delete(key)
   214  		return key, true
   215  	}
   216  	var zeroValue T
   217  	return zeroValue, false
   218  }
   219  
   220  // Len returns the size of the set.
   221  func (s Set[T]) Len() int {
   222  	return len(s)
   223  }
   224  
   225  func less[T ordered](lhs, rhs T) bool {
   226  	return lhs < rhs
   227  }