sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/layeredsets/string.go (about) 1 /* 2 Copyright 2020 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 layeredsets 18 19 import ( 20 "math/rand" 21 "sort" 22 23 "k8s.io/apimachinery/pkg/util/sets" 24 ) 25 26 // String is a layered set implemented as a slice of sets.Set[string]. 27 type String []sets.Set[string] 28 29 // NewString creates a String from a list of values. 30 func NewString(items ...string) String { 31 ss := String{} 32 ss.Insert(0, items...) 33 return ss 34 } 35 36 // NewStringFromSlices creates a String from a list of sets. 37 func NewStringFromSlices(items ...[]string) String { 38 ss := String{} 39 for i, s := range items { 40 ss.Insert(i, s...) 41 } 42 return ss 43 } 44 45 // Insert adds items to the set. 46 func (s *String) Insert(layerID int, items ...string) { 47 for len(*s) < layerID+1 { 48 *s = append(*s, sets.New[string]()) 49 } 50 for _, item := range items { 51 if !s.Has(item) { 52 (*s)[layerID].Insert(item) 53 } 54 } 55 } 56 57 // Delete removes all items from the set. 58 func (s String) Delete(items ...string) { 59 for _, layer := range s { 60 layer.Delete(items...) 61 } 62 } 63 64 // Has returns true if and only if item is contained in the set. 65 func (s String) Has(item string) bool { 66 for _, layer := range s { 67 if layer.Has(item) { 68 return true 69 } 70 } 71 return false 72 } 73 74 // Difference returns a set of objects that are not in s2 75 func (s String) Difference(s2 sets.Set[string]) String { 76 result := NewString() 77 for layerID, layer := range s { 78 for _, key := range sets.List(layer) { 79 if !s2.Has(key) { 80 result.Insert(layerID, key) 81 } 82 } 83 } 84 return result 85 } 86 87 // Union returns a new set which includes items in either s1 or s2. 88 func (s String) Union(s2 String) String { 89 result := NewString() 90 for layerID, layer := range s { 91 result.Insert(layerID, sets.List(layer)...) 92 } 93 for layerID, layer := range s2 { 94 result.Insert(layerID, sets.List(layer)...) 95 } 96 return result 97 } 98 99 // PopRandom randomly selects an element and pops it. 100 func (s String) PopRandom() string { 101 for _, layer := range s { 102 if layer.Len() > 0 { 103 list := sets.List(layer) 104 sort.Strings(list) 105 sel := list[rand.Intn(len(list))] 106 s.Delete(sel) 107 return sel 108 } 109 } 110 return "" 111 } 112 113 // Equal returns true if and only if s1 is equal (as a set) to s2. 114 func (s String) Equal(s2 String) bool { 115 if s.Len() != s2.Len() { 116 return false 117 } 118 for layerID, layer := range s { 119 if !s2[layerID].Equal(layer) { 120 return false 121 } 122 } 123 return true 124 } 125 126 // List returns the contents as a sorted string slice, respecting layers. 127 func (s String) List() []string { 128 var res []string 129 for _, layer := range s { 130 res = append(res, sets.List(layer)...) 131 } 132 return res 133 } 134 135 // UnsortedList returns the slice with contents in random order, respecting layers. 136 func (s String) UnsortedList() []string { 137 var res []string 138 for _, layer := range s { 139 res = append(res, layer.UnsortedList()...) 140 } 141 return res 142 } 143 144 // Set converts the multiset into a regular sets.Set[string] for compatibility. 145 func (s String) Set() sets.Set[string] { 146 ss := sets.Set[string]{} 147 return ss.Insert(s.List()...) 148 } 149 150 // Len returns the size of the set. 151 func (s String) Len() int { 152 var i int 153 for _, layer := range s { 154 i += layer.Len() 155 } 156 return i 157 }