package utils import ( "encoding/json" "sort" ) // DistinctAny remove duplicate elements func DistinctAny[E any, K comparable](es []E, fn func(e E) K) []E { v := make([]E, 0, len(es)) tmp := map[K]struct{}{} for i := 0; i < len(es); i++ { t := es[i] k := fn(t) if _, ok := tmp[k]; !ok { tmp[k] = struct{}{} v = append(v, t) } } return v } // Distinct remove duplicate elements func Distinct[T comparable](ts []T) []T { return DistinctAny(ts, func(t T) T { return t }) } // Delete delete slice element, support negative number to delete the penultimate func Delete[E any](es []E, index ...int) []E { switch len(index) { case 0: return es case 1: i := index[0] if i < 0 { i = len(es) + i } if len(es) <= i { return es } return append(es[:i], es[i+1:]...) default: tmp := make(map[int]struct{}) for _, i := range index { if i < 0 { i = len(es) + i } tmp[i] = struct{}{} } v := make([]E, 0, len(es)) for i := 0; i < len(es); i++ { if _, ok := tmp[i]; !ok { v = append(v, es[i]) } } return v } } // DeleteAt delete slice element, support negative number to delete the penultimate func DeleteAt[E any](es *[]E, index ...int) []E { v := Delete(*es, index...) *es = v return v } // IndexAny get the index of the element func IndexAny[E any, K comparable](es []E, e E, fn func(e E) K) int { k := fn(e) for i := 0; i < len(es); i++ { if fn(es[i]) == k { return i } } return -1 } // IndexOf get the index of the element func IndexOf[E comparable](es []E, e E) int { return IndexAny(es, e, func(t E) E { return t }) } // Contain include element or not func Contain[E comparable](es []E, e E) bool { return IndexOf(es, e) >= 0 } // SliceToMapOkAny slice to map func SliceToMapOkAny[E any, K comparable, V any](es []E, fn func(e E) (K, V, bool)) map[K]V { kv := make(map[K]V) for i := 0; i < len(es); i++ { t := es[i] if k, v, ok := fn(t); ok { kv[k] = v } } return kv } // SliceToMapAny slice to map func SliceToMapAny[E any, K comparable, V any](es []E, fn func(e E) (K, V)) map[K]V { return SliceToMapOkAny(es, func(e E) (K, V, bool) { k, v := fn(e) return k, v, true }) } // SliceToMap slice to map func SliceToMap[E any, K comparable](es []E, fn func(e E) K) map[K]E { return SliceToMapOkAny[E, K, E](es, func(e E) (K, E, bool) { k := fn(e) return k, e, true }) } // SliceSetAny slice to map[K]struct{} func SliceSetAny[E any, K comparable](es []E, fn func(e E) K) map[K]struct{} { return SliceToMapAny(es, func(e E) (K, struct{}) { return fn(e), struct{}{} }) } // SliceSet slice to map[E]struct{} func SliceSet[E comparable](es []E) map[E]struct{} { return SliceSetAny(es, func(e E) E { return e }) } // HasKey get whether the map contains key func HasKey[K comparable, V any](m map[K]V, k K) bool { if m == nil { return false } _, ok := m[k] return ok } // Min get minimum value func Min[E Ordered](e ...E) E { v := e[0] for _, t := range e[1:] { if v > t { v = t } } return v } // Max get maximum value func Max[E Ordered](e ...E) E { v := e[0] for _, t := range e[1:] { if v < t { v = t } } return v } // BothExistAny get elements common to multiple slices func BothExistAny[E any, K comparable](es [][]E, fn func(e E) K) []E { if len(es) == 0 { return []E{} } var idx int ei := make([]map[K]E, len(es)) for i := 0; i < len(ei); i++ { e := es[i] if len(e) == 0 { return []E{} } kv := make(map[K]E) for j := 0; j < len(e); j++ { t := e[j] k := fn(t) kv[k] = t } ei[i] = kv if len(kv) < len(ei[idx]) { idx = i } } v := make([]E, 0, len(ei[idx])) for k := range ei[idx] { all := true for i := 0; i < len(ei); i++ { if i == idx { continue } if _, ok := ei[i][k]; !ok { all = false break } } if !all { continue } v = append(v, ei[idx][k]) } return v } // BothExist get elements common to multiple slices func BothExist[E comparable](es ...[]E) []E { return BothExistAny(es, func(e E) E { return e }) } // CompleteAny complete inclusion func CompleteAny[K comparable, E any](ks []K, es []E, fn func(e E) K) bool { a := SliceSetAny(es, fn) for k := range SliceSet(ks) { if !HasKey(a, k) { return false } delete(a, k) } return len(a) == 0 } // MapKey get map keys func MapKey[K comparable, V any](kv map[K]V) []K { ks := make([]K, 0, len(kv)) for k := range kv { ks = append(ks, k) } return ks } // MapValue get map values func MapValue[K comparable, V any](kv map[K]V) []V { vs := make([]V, 0, len(kv)) for k := range kv { vs = append(vs, kv[k]) } return vs } // Sort basic type sorting func Sort[E Ordered](es []E, asc bool) []E { SortAny(es, func(a, b E) bool { if asc { return a < b } else { return a > b } }) return es } // SortAny custom sort method func SortAny[E any](es []E, fn func(a, b E) bool) { sort.Sort(&sortSlice[E]{ ts: es, fn: fn, }) } // If true -> a, false -> b func If[T any](isa bool, a, b T) T { if isa { return a } return b } func UniqueJoin(s ...string) string { data, _ := json.Marshal(s) return string(data) } type sortSlice[E any] struct { ts []E fn func(a, b E) bool } func (o *sortSlice[E]) Len() int { return len(o.ts) } func (o *sortSlice[E]) Less(i, j int) bool { return o.fn(o.ts[i], o.ts[j]) } func (o *sortSlice[E]) Swap(i, j int) { o.ts[i], o.ts[j] = o.ts[j], o.ts[i] } // Ordered types that can be sorted type Ordered interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string }