go-pkg/slice/slice.go

163 lines
2.8 KiB
Go
Raw Permalink Normal View History

2023-07-12 12:43:25 -06:00
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
}