From 868682aa20985d2e038e1b8ca606dbd502993e62 Mon Sep 17 00:00:00 2001 From: jingyuexing <19589872+jingyuexing@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:06:40 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20support=20generics,add=20ne?= =?UTF-8?q?w=20feature=20=20=20=20-=20`Reduce`=20=20=20=20-=20`Chunk`=20?= =?UTF-8?q?=20=20=20-=20`Map`=20=20=20=20-=20`Filter`=20=20=20=20-=20=20Gr?= =?UTF-8?q?oupBy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func.go | 33 +++++++++++++------ slice.go | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ toggle.go | 23 +++++++++++++ utils.go | 24 -------------- utils_test.go | 49 ++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 34 deletions(-) create mode 100644 slice.go create mode 100644 toggle.go diff --git a/func.go b/func.go index aa0eed6..ac56dfe 100644 --- a/func.go +++ b/func.go @@ -8,19 +8,19 @@ import ( // PipeCallback executes a series of functions where the output of each function is passed as input to the next function. // Returns a function that can be invoked to run the entire execution process. func PipeCallback[T any](fns ...func(args T) T) func(args T) T { - return func(args T) T { - result := args - for _, fn := range fns { - result = fn(result) - } - return result - } + return func(args T) T { + result := args + for _, fn := range fns { + result = fn(result) + } + return result + } } -func Times(cb func(...any) any, x int) func(...any) any { - value := any(nil) +func Times[T any](cb func(args ...T) T, x int) func(...T) T { + var value T times := 0 - return func(args ...any) any { + return func(args ...T) T { if times < x { defer func() { if r := recover(); r != nil { @@ -38,3 +38,16 @@ func Times(cb func(...any) any, x int) func(...any) any { return value } } + +func Compose[T any](funcs ...func(args ...T) T) func(args ...T) T { + callback := func(a func(args ...T) T, b func(args ...T) T) func(args ...T) T { + return func(args ...T) T { + return a(b(args...)) + } + } + startFunc := funcs[0] + for i := 1; i < len(funcs); i++ { + startFunc = callback(startFunc, funcs[i]) + } + return startFunc +} diff --git a/slice.go b/slice.go new file mode 100644 index 0000000..7e008db --- /dev/null +++ b/slice.go @@ -0,0 +1,90 @@ +package utils + + +func Chunk[T any](slice []T, size int) [][]T { + var chunks [][]T + for i := 0; i < len(slice); i += size { + end := i + size + if end > len(slice) { + end = len(slice) + } + chunks = append(chunks, slice[i:end]) + } + return chunks +} + + +func Reduce[T any](slice []T, reducer func(T, T) T, initialValue T) T { + result := initialValue + + for _, val := range slice { + result = reducer(result, val) + } + + return result +} + +func Map[T any](slice []T, mapper func(T) T) []T { + result := make([]T, len(slice)) + + for i, val := range slice { + result[i] = mapper(val) + } + + return result +} + +func Filter[T any](slice []T, predicate func(T) bool) []T { + var result []T + + for _, val := range slice { + if predicate(val) { + result = append(result, val) + } + } + + return result +} + +func PadEnd[T any](slice []T, targetLength int, padValue T) []T { + currentLength := len(slice) + paddingLength := targetLength - currentLength + if paddingLength <= 0 { + return slice + } + newSlice := make([]T, 0,paddingLength) + for i := 0; i < paddingLength; i++ { + newSlice = append(newSlice, padValue) + } + newSlice = append(slice, newSlice...) + + return newSlice +} + +func PadStart[T any](slice []T, targetLength int, padValue T) []T { + currentLength := len(slice) + paddingLength := targetLength - currentLength + if paddingLength <= 0 { + return slice + } + + newSlice := make([]T, 0, paddingLength) + for i := 0; i < paddingLength; i++ { + newSlice = append(newSlice, padValue) + } + + newSlice = append(newSlice, slice...) + + return newSlice +} + +func GroupBy[T any, K comparable](slice []T, getKey func(T) K) map[K][]T { + groups := make(map[K][]T) + + for _, item := range slice { + key := getKey(item) + groups[key] = append(groups[key], item) + } + + return groups +} diff --git a/toggle.go b/toggle.go new file mode 100644 index 0000000..887aca6 --- /dev/null +++ b/toggle.go @@ -0,0 +1,23 @@ +package utils +type Toggler[T any] interface { + Switch() T + Value() T +} + +type toggleValue[T any] struct { + values []T + currentIdx int +} + +func (t *toggleValue[T]) Switch() T { + t.currentIdx = (t.currentIdx + 1) % len(t.values) + return t.Value() +} + +func (t *toggleValue[T]) Value() T { + return t.values[t.currentIdx] +} + +func UseToggle[T any](value ...T) Toggler[T] { + return &toggleValue[T]{values: value, currentIdx: 0} +} diff --git a/utils.go b/utils.go index f6bff0f..54387d8 100644 --- a/utils.go +++ b/utils.go @@ -170,18 +170,6 @@ func Map2Struct(source map[string]any, bindingTarget any) { } } -func Compose[T any](funcs ...func(args ...T) T) func(args ...T) T { - callback := func(a func(args ...T) T, b func(args ...T) T) func(args ...T) T { - return func(args ...T) T { - return a(b(args...)) - } - } - startFunc := funcs[0] - for i := 1; i < len(funcs); i++ { - startFunc = callback(startFunc, funcs[i]) - } - return startFunc -} func TimeDuration(duration string) (time.Time, error) { const ( @@ -214,15 +202,3 @@ func TimeDuration(duration string) (time.Time, error) { } return time.Now().Add(time.Duration(durationSecond) * time.Second).UTC(), nil } - -func Chunk(slice []int, size int) [][]int { - var chunks [][]int - for i := 0; i < len(slice); i += size { - end := i + size - if end > len(slice) { - end = len(slice) - } - chunks = append(chunks, slice[i:end]) - } - return chunks -} diff --git a/utils_test.go b/utils_test.go index 30d22cd..7b2683b 100644 --- a/utils_test.go +++ b/utils_test.go @@ -51,3 +51,52 @@ func TestMap2Struct(t *testing.T) { t.Error("Not Pass") } } + +func TestToggle(t *testing.T) { + toggle1 := utils.UseToggle("on","off") + toggle1.Switch() + if toggle1.Value() != "off" { + t.Error("not pass") + } + if toggle1.Switch() != "on" { + t.Error("not pass") + } + + toggle2 := utils.UseToggle(true,false) + if toggle2.Value() != true { + t.Error("not pass") + } + + if toggle2.Switch() != false { + t.Error("not pass") + } + + toggle3 := utils.UseToggle(1,2,3,4,5,6,7,8,9) + if toggle3.Value() != 1 { + t.Error("not pass") + } + toggle3.Switch() + toggle3.Switch() + toggle3.Switch() + toggle3.Switch() + if toggle3.Value() != 5 { + t.Error("not pass") + } + +} + + +func TestTimes(t *testing.T) { + utils.Times(func(t ...string) string { + return "hello world" + },2) +} + +func TestReduce(t *testing.T) { + sum := utils.Reduce([]int{1,2,3,5,6},func(accumulator, currentValue int) int { + return accumulator + currentValue + },0) + if sum != 17 { + t.Error("not pass") + } +}