github.com/prysmaticlabs/prysm@v1.4.4/shared/sliceutil/slice.go (about) 1 package sliceutil 2 3 import ( 4 "strings" 5 6 types "github.com/prysmaticlabs/eth2-types" 7 ) 8 9 // SubsetUint64 returns true if the first array is 10 // completely contained in the second array with time 11 // complexity of approximately o(n). 12 func SubsetUint64(a, b []uint64) bool { 13 if len(a) > len(b) { 14 return false 15 } 16 17 set := make(map[uint64]uint64, len(b)) 18 for _, v := range b { 19 set[v]++ 20 } 21 22 for _, v := range a { 23 if count, found := set[v]; !found { 24 return false 25 } else if count < 1 { 26 return false 27 } else { 28 set[v] = count - 1 29 } 30 } 31 return true 32 } 33 34 // IntersectionUint64 of any number of uint64 slices with time 35 // complexity of approximately O(n) leveraging a map to 36 // check for element existence off by a constant factor 37 // of underlying map efficiency. 38 func IntersectionUint64(s ...[]uint64) []uint64 { 39 if len(s) == 0 { 40 return []uint64{} 41 } 42 if len(s) == 1 { 43 return s[0] 44 } 45 intersect := make([]uint64, 0) 46 m := make(map[uint64]int) 47 for _, k := range s[0] { 48 m[k] = 1 49 } 50 for i, num := 1, len(s); i < num; i++ { 51 for _, k := range s[i] { 52 // Increment and check only if item is present in both, and no increment has happened yet. 53 if _, found := m[k]; found && i == m[k] { 54 m[k]++ 55 if m[k] == num { 56 intersect = append(intersect, k) 57 } 58 } 59 } 60 } 61 return intersect 62 } 63 64 // UnionUint64 of any number of uint64 slices with time 65 // complexity of approximately O(n) leveraging a map to 66 // check for element existence off by a constant factor 67 // of underlying map efficiency. 68 func UnionUint64(s ...[]uint64) []uint64 { 69 if len(s) == 0 { 70 return []uint64{} 71 } 72 if len(s) == 1 { 73 return s[0] 74 } 75 set := s[0] 76 m := make(map[uint64]bool) 77 for i := 1; i < len(s); i++ { 78 a := s[i-1] 79 b := s[i] 80 for j := 0; j < len(a); j++ { 81 m[a[j]] = true 82 } 83 for j := 0; j < len(b); j++ { 84 if _, found := m[b[j]]; !found { 85 set = append(set, b[j]) 86 } 87 } 88 } 89 return set 90 } 91 92 // SetUint64 returns a slice with only unique 93 // values from the provided list of indices. 94 func SetUint64(a []uint64) []uint64 { 95 // Remove duplicates indices. 96 intMap := map[uint64]bool{} 97 cleanedIndices := make([]uint64, 0, len(a)) 98 for _, idx := range a { 99 if intMap[idx] { 100 continue 101 } 102 intMap[idx] = true 103 cleanedIndices = append(cleanedIndices, idx) 104 } 105 return cleanedIndices 106 } 107 108 // IsUint64Sorted verifies if a uint64 slice is sorted in ascending order. 109 func IsUint64Sorted(a []uint64) bool { 110 if len(a) == 0 || len(a) == 1 { 111 return true 112 } 113 for i := 1; i < len(a); i++ { 114 if a[i-1] > a[i] { 115 return false 116 } 117 } 118 return true 119 } 120 121 // NotUint64 returns the uint64 in slice b that are 122 // not in slice a with time complexity of approximately 123 // O(n) leveraging a map to check for element existence 124 // off by a constant factor of underlying map efficiency. 125 func NotUint64(a, b []uint64) []uint64 { 126 set := make([]uint64, 0) 127 m := make(map[uint64]bool) 128 129 for i := 0; i < len(a); i++ { 130 m[a[i]] = true 131 } 132 for i := 0; i < len(b); i++ { 133 if _, found := m[b[i]]; !found { 134 set = append(set, b[i]) 135 } 136 } 137 return set 138 } 139 140 // IsInUint64 returns true if a is in b and False otherwise. 141 func IsInUint64(a uint64, b []uint64) bool { 142 for _, v := range b { 143 if a == v { 144 return true 145 } 146 } 147 return false 148 } 149 150 // IntersectionInt64 of any number of int64 slices with time 151 // complexity of approximately O(n) leveraging a map to 152 // check for element existence off by a constant factor 153 // of underlying map efficiency. 154 func IntersectionInt64(s ...[]int64) []int64 { 155 if len(s) == 0 { 156 return []int64{} 157 } 158 if len(s) == 1 { 159 return s[0] 160 } 161 intersect := make([]int64, 0) 162 m := make(map[int64]int) 163 for _, k := range s[0] { 164 m[k] = 1 165 } 166 for i, num := 1, len(s); i < num; i++ { 167 for _, k := range s[i] { 168 if _, found := m[k]; found && i == m[k] { 169 m[k]++ 170 if m[k] == num { 171 intersect = append(intersect, k) 172 } 173 } 174 } 175 } 176 return intersect 177 } 178 179 // UnionInt64 of any number of int64 slices with time 180 // complexity of approximately O(n) leveraging a map to 181 // check for element existence off by a constant factor 182 // of underlying map efficiency. 183 func UnionInt64(s ...[]int64) []int64 { 184 if len(s) == 0 { 185 return []int64{} 186 } 187 if len(s) == 1 { 188 return s[0] 189 } 190 set := s[0] 191 m := make(map[int64]bool) 192 for i := 1; i < len(s); i++ { 193 a := s[i-1] 194 b := s[i] 195 for j := 0; j < len(a); j++ { 196 m[a[j]] = true 197 } 198 for j := 0; j < len(b); j++ { 199 if _, found := m[b[j]]; !found { 200 set = append(set, b[j]) 201 } 202 } 203 } 204 return set 205 } 206 207 // NotInt64 returns the int64 in slice a that are 208 // not in slice b with time complexity of approximately 209 // O(n) leveraging a map to check for element existence 210 // off by a constant factor of underlying map efficiency. 211 func NotInt64(a, b []int64) []int64 { 212 set := make([]int64, 0) 213 m := make(map[int64]bool) 214 215 for i := 0; i < len(a); i++ { 216 m[a[i]] = true 217 } 218 for i := 0; i < len(b); i++ { 219 if _, found := m[b[i]]; !found { 220 set = append(set, b[i]) 221 } 222 } 223 return set 224 } 225 226 // IsInInt64 returns true if a is in b and False otherwise. 227 func IsInInt64(a int64, b []int64) bool { 228 for _, v := range b { 229 if a == v { 230 return true 231 } 232 } 233 return false 234 } 235 236 // UnionByteSlices returns the all elements between sets of byte slices. 237 func UnionByteSlices(s ...[][]byte) [][]byte { 238 if len(s) == 0 { 239 return [][]byte{} 240 } 241 if len(s) == 1 { 242 return s[0] 243 } 244 set := s[0] 245 m := make(map[string]bool) 246 for i := 1; i < len(s); i++ { 247 for j := 0; j < len(s[i-1]); j++ { 248 m[string(s[i-1][j])] = true 249 } 250 for j := 0; j < len(s[i]); j++ { 251 if _, found := m[string(s[i][j])]; !found { 252 set = append(set, s[i][j]) 253 } 254 } 255 } 256 return set 257 } 258 259 // IntersectionByteSlices returns the common elements between sets of byte slices. 260 func IntersectionByteSlices(s ...[][]byte) [][]byte { 261 if len(s) == 0 { 262 return [][]byte{} 263 } 264 if len(s) == 1 { 265 return s[0] 266 } 267 inter := make([][]byte, 0) 268 m := make(map[string]int) 269 for _, k := range s[0] { 270 m[string(k)] = 1 271 } 272 for i, num := 1, len(s); i < num; i++ { 273 for _, k := range s[i] { 274 if _, found := m[string(k)]; found && i == m[string(k)] { 275 m[string(k)]++ 276 if m[string(k)] == num { 277 inter = append(inter, k) 278 } 279 } 280 } 281 } 282 return inter 283 } 284 285 // SplitCommaSeparated values from the list. Example: []string{"a,b", "c,d"} becomes []string{"a", "b", "c", "d"}. 286 func SplitCommaSeparated(arr []string) []string { 287 var result []string 288 for _, val := range arr { 289 result = append(result, strings.Split(val, ",")...) 290 } 291 return result 292 } 293 294 // SplitOffset returns the start index of a given list splits into chunks, 295 // it computes (listsize * index) / chunks. 296 // 297 // Spec pseudocode definition: 298 // def get_split_offset(list_size: int, chunks: int, index: int) -> int: 299 // """ 300 // Returns a value such that for a list L, chunk count k and index i, 301 // split(L, k)[i] == L[get_split_offset(len(L), k, i): get_split_offset(len(L), k, i+1)] 302 // """ 303 // return (list_size * index) // chunks 304 func SplitOffset(listSize, chunks, index uint64) uint64 { 305 return (listSize * index) / chunks 306 } 307 308 // IntersectionSlot of any number of types.Slot slices with time 309 // complexity of approximately O(n) leveraging a map to 310 // check for element existence off by a constant factor 311 // of underlying map efficiency. 312 func IntersectionSlot(s ...[]types.Slot) []types.Slot { 313 if len(s) == 0 { 314 return []types.Slot{} 315 } 316 if len(s) == 1 { 317 return s[0] 318 } 319 intersect := make([]types.Slot, 0) 320 m := make(map[types.Slot]int) 321 for _, k := range s[0] { 322 m[k] = 1 323 } 324 for i, num := 1, len(s); i < num; i++ { 325 for _, k := range s[i] { 326 // Increment and check only if item is present in both, and no increment has happened yet. 327 if _, found := m[k]; found && i == m[k] { 328 m[k]++ 329 if m[k] == num { 330 intersect = append(intersect, k) 331 } 332 } 333 } 334 } 335 return intersect 336 } 337 338 // NotSlot returns the types.Slot in slice b that are 339 // not in slice a with time complexity of approximately 340 // O(n) leveraging a map to check for element existence 341 // off by a constant factor of underlying map efficiency. 342 func NotSlot(a, b []types.Slot) []types.Slot { 343 set := make([]types.Slot, 0) 344 m := make(map[types.Slot]bool) 345 346 for i := 0; i < len(a); i++ { 347 m[a[i]] = true 348 } 349 for i := 0; i < len(b); i++ { 350 if _, found := m[b[i]]; !found { 351 set = append(set, b[i]) 352 } 353 } 354 return set 355 } 356 357 // IsInSlots returns true if a is in b and False otherwise. 358 func IsInSlots(a types.Slot, b []types.Slot) bool { 359 for _, v := range b { 360 if a == v { 361 return true 362 } 363 } 364 return false 365 }