package slice import ( "go.sour.is/pkg/math" ) // FilterType returns a subset that matches the type. func FilterType[T any](in ...any) []T { lis := make([]T, 0, len(in)) for _, u := range in { if t, ok := u.(T); ok { lis = append(lis, t) } } return lis } func FilterFn[T any](fn func(T) bool, in ...T) []T { lis := make([]T, 0, len(in)) for _, t := range in { if fn(t) { lis = append(lis, t) } } return lis } // Find returns the first of type found. or false if not found. func Find[T any](in ...any) (T, bool) { return First(FilterType[T](in...)...) } func FindFn[T any](fn func(T) bool, in ...T) (T, bool) { return First(FilterFn(fn, in...)...) } // First returns the first element in a slice. func First[T any](in ...T) (T, bool) { if len(in) == 0 { var zero T return zero, false } return in[0], true } // Map applys func to each element s and returns results as slice. func Map[T, U any](f func(int, T) U) func(...T) []U { return func(lis ...T) []U { r := make([]U, len(lis)) for i, v := range lis { r[i] = f(i, v) } return r } } func Reduce[T, R any](r R, fn func(T, R, int) R) func(...T) R { return func(lis ...T) R { for i, t := range lis { r = fn(t, r, i) } return r } } type Pair[K comparable, V any] struct { Key K Value V } func FromMap[K comparable, V any](m map[K]V) (keys []K, values []V) { if m == nil { return nil, nil } keys = FromMapKeys(m) return keys, FromMapValues(m, keys) } func FromMapKeys[K comparable, V any](m map[K]V) (keys []K) { if m == nil { return nil } keys = make([]K, 0, len(m)) for k := range m { keys = append(keys, k) } return keys } func FromMapValues[K comparable, V any](m map[K]V, keys []K) (values []V) { if m == nil { return nil } values = make([]V, 0, len(keys)) for _, k := range keys { values = append(values, m[k]) } return values } func ToMap[K comparable, V any](keys []K, values []V) (m map[K]V) { m = make(map[K]V, len(keys)) for i := range keys { if len(values) < i { break } m[keys[i]] = values[i] } return m } func Zip[K comparable, V any](k []K, v []V) []Pair[K, V] { lis := make([]Pair[K, V], math.Max(len(k), len(v))) for i := range lis { if k != nil && len(k) > i { lis[i].Key = k[i] } if v != nil && len(v) > i { lis[i].Value = v[i] } } return lis } func Align[T any](k []T, v []T, less func(T, T) bool) []Pair[*T, *T] { lis := make([]Pair[*T, *T], 0, math.Max(len(k), len(v))) var j int for i := 0; i < len(k); { if j >= len(v) || less(k[i], v[j]) { lis = append(lis, Pair[*T, *T]{&k[i], nil}) i++ continue } if less(v[j], k[i]) { lis = append(lis, Pair[*T, *T]{nil, &v[j]}) j++ continue } lis = append(lis, Pair[*T, *T]{&k[i], &v[j]}) i++ j++ } for ; j < len(v); j++ { lis = append(lis, Pair[*T, *T]{nil, &v[j]}) } return lis }