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  }