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  }