From 778e3e5cd275e69509447b110c842213a4c29a23 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 2 Feb 2023 17:49:19 +0800 Subject: [PATCH] 1 --- pkg/utilsv2/slice.go | 229 +++++++++++++++++++++++++++++--------- pkg/utilsv2/slice_test.go | 34 ++++++ 2 files changed, 211 insertions(+), 52 deletions(-) diff --git a/pkg/utilsv2/slice.go b/pkg/utilsv2/slice.go index edeb1dc12..ab0d2e945 100644 --- a/pkg/utilsv2/slice.go +++ b/pkg/utilsv2/slice.go @@ -4,12 +4,12 @@ import ( "sort" ) -// DistinctAny 切片去重 -func DistinctAny[T any, V comparable](ts []T, fn func(t T) V) []T { - v := make([]T, 0, len(ts)) - tmp := map[V]struct{}{} - for i := 0; i < len(ts); i++ { - t := ts[i] +// 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{}{} @@ -19,80 +19,204 @@ func DistinctAny[T any, V comparable](ts []T, fn func(t T) V) []T { return v } -// Distinct 切片去重 +// Distinct remove duplicate elements func Distinct[T comparable](ts []T) []T { return DistinctAny(ts, func(t T) T { return t }) } -// DeleteAt 删除切片元素, 支持负数删除倒数第几个 -func DeleteAt[T any](ts []T, index ...int) []T { +// DeleteAt delete slice element, support negative number to delete the penultimate +func DeleteAt[E any](es []E, index ...int) []E { switch len(index) { case 0: - return ts + return es case 1: i := index[0] if i < 0 { - i = len(ts) + i + i = len(es) + i } - if len(ts) <= i { - return ts + if len(es) <= i { + return es } - return append(ts[:i], ts[i+1:]...) + return append(es[:i], es[i+1:]...) default: tmp := make(map[int]struct{}) for _, i := range index { if i < 0 { - i = len(ts) + i + i = len(es) + i } tmp[i] = struct{}{} } - v := make([]T, 0, len(ts)) - for i := 0; i < len(ts); i++ { + v := make([]E, 0, len(es)) + for i := 0; i < len(es); i++ { if _, ok := tmp[i]; !ok { - v = append(v, ts[i]) + v = append(v, es[i]) } } return v } } -// IndexAny 获取元素所在的下标 -func IndexAny[T any, V comparable](ts []T, t T, fn func(t T) V) int { - k := fn(t) - for i := 0; i < len(ts); i++ { - if fn(ts[i]) == k { +// 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 可比较的元素index下标 -func IndexOf[T comparable](ts []T, t T) int { - return IndexAny(ts, t, func(t T) T { +// 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 }) } -// IsContain 是否包含元素 -func IsContain[T comparable](ts []T, t T) bool { - return IndexOf(ts, t) >= 0 +// Contain include element or not +func Contain[E comparable](es []E, e E) bool { + return IndexOf(es, e) >= 0 } -// SliceToMap 切片转map -func SliceToMap[T any, K comparable](ts []T, fn func(t T) K) map[K]T { - kv := make(map[K]T) - for i := 0; i < len(ts); i++ { - t := ts[i] - k := fn(t) - kv[k] = t +// 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 } -// MapKey map获取所有key +// 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 { @@ -101,7 +225,7 @@ func MapKey[K comparable, V any](kv map[K]V) []K { return ks } -// MapValue map获取所有key +// 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 { @@ -110,43 +234,44 @@ func MapValue[K comparable, V any](kv map[K]V) []V { return vs } -// Sort 排序 -func Sort[T Ordered](ts []T, asc bool) []T { - SortAny(ts, func(a, b T) bool { +// 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 ts + return es } -// SortAny 排序 -func SortAny[T any](ts []T, fn func(a, b T) bool) { - sort.Sort(&sortSlice[T]{ - ts: ts, +// SortAny custom sort method +func SortAny[E any](es []E, fn func(a, b E) bool) { + sort.Sort(&sortSlice[E]{ + ts: es, fn: fn, }) } -type sortSlice[T any] struct { - ts []T - fn func(a, b T) bool +type sortSlice[E any] struct { + ts []E + fn func(a, b E) bool } -func (o *sortSlice[T]) Len() int { +func (o *sortSlice[E]) Len() int { return len(o.ts) } -func (o *sortSlice[T]) Less(i, j int) bool { +func (o *sortSlice[E]) Less(i, j int) bool { return o.fn(o.ts[i], o.ts[j]) } -func (o *sortSlice[T]) Swap(i, j int) { +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 } diff --git a/pkg/utilsv2/slice_test.go b/pkg/utilsv2/slice_test.go index 2dc81d80a..fd18c497e 100644 --- a/pkg/utilsv2/slice_test.go +++ b/pkg/utilsv2/slice_test.go @@ -46,5 +46,39 @@ func TestIndexOf(t *testing.T) { func TestSort(t *testing.T) { arr := []int{1, 1, 1, 4, 4, 5, 2, 3, 3, 3, 6} fmt.Println(Sort(arr, false)) +} + +func TestBothExist(t *testing.T) { + arr1 := []int{1, 1, 1, 4, 4, 5, 2, 3, 3, 3, 6} + arr2 := []int{6, 1, 3} + arr3 := []int{5, 1, 3, 6} + fmt.Println(BothExist(arr1, arr2, arr3)) +} + +func TestCompleteAny(t *testing.T) { + type Item struct { + ID int + Value string + } + + ids := []int{1, 2, 3, 4, 5, 6, 7, 8} + + var list []Item + + for _, id := range ids { + list = append(list, Item{ + ID: id, + Value: fmt.Sprintf("%d", id*1000), + }) + } + + list = DeleteAt(list, -1) + ids = DeleteAt(ids, -1) + + ok := CompleteAny(ids, list, func(t Item) int { + return t.ID + }) + + fmt.Printf("%+v\n", ok) }