gitlab.com/picnic-app/backend/role-api@v0.0.0-20230614140944-06a76ff3696d/internal/util/slice/slice.go (about) 1 package slice 2 3 import "github.com/pkg/errors" 4 5 func Batch[T any](s []T, batchSize int, f func(batch []T) error) error { 6 if batchSize <= 0 { 7 return nil 8 } 9 10 for start := 0; start < len(s); start += batchSize { 11 end := min(start+batchSize, len(s)) 12 err := f(s[start:end]) 13 if err != nil { 14 return errors.Wrapf(err, "batch processing %T from %d to %d", s, start, end) 15 } 16 } 17 return nil 18 } 19 20 func Filter[T any](s []T, ok func(v T) bool) []T { 21 var out []T 22 for _, v := range s { 23 if ok(v) { 24 out = append(out, v) 25 } 26 } 27 return out 28 } 29 30 // Reorder sorts s in the order of keys. The values in keys must be unique, but 31 // the function is tolerant of non-unique values in s. Values from s not present 32 // in keys will be skipped. 33 func Reorder[T any, K comparable](keys []K, s []T, key func(obj T) K) []T { 34 m, n := make(map[K][]T, len(s)), 0 35 for i, v := range s { 36 k := key(v) 37 if tmp := m[k]; len(tmp) == 0 { 38 m[k] = s[i : i+1 : i+1] // To avoid allocations for unique elements. 39 } else { 40 m[k], n = append(tmp, v), n+1 41 } 42 } 43 44 s = make([]T, 0, len(keys)+n) 45 for _, key := range keys { 46 if v, ok := m[key]; ok { 47 s = append(s, v...) 48 } 49 } 50 return s 51 } 52 53 func ValuesByKey[T, K any](s []T, key func(obj T) K) []K { 54 v := make([]K, len(s)) 55 for i, obj := range s { 56 v[i] = key(obj) 57 } 58 return v 59 } 60 61 func UniqueValues[T any, K comparable](s []T, key func(obj T) K) []K { 62 v := make([]K, len(s)) 63 for i, obj := range s { 64 v[i] = key(obj) 65 } 66 return Unique(v) 67 } 68 69 func Convert[A, B any](f func(A) B, a ...A) []B { 70 result := make([]B, len(a)) 71 for i, a := range a { 72 result[i] = f(a) 73 } 74 return result 75 } 76 77 func ConvertPointers[A, B any](f func(A) B, a ...A) []*B { 78 return Convert(func(a A) *B { v := f(a); return &v }, a...) 79 } 80 81 // Unique returns unique values from s. The function reuses s to store values, so 82 // s should not be used afterward. The order of the values is preserved. 83 func Unique[T comparable](s []T) []T { 84 set, n, ok := make(map[T]struct{}, len(s)), 0, false 85 for _, v := range s { 86 if _, ok = set[v]; !ok { 87 s[n], set[v], n = v, struct{}{}, n+1 88 } 89 } 90 return s[:n] 91 } 92 93 func min(a, b int) int { 94 if a < b { 95 return a 96 } 97 return b 98 }