From 24c0d95112f62d70ba66f121073fad9d051347e5 Mon Sep 17 00:00:00 2001 From: donutloop Date: Mon, 10 Jan 2022 12:52:23 +0100 Subject: [PATCH] Slice: reverse and shufffle v2 (#19) * Slice: reverse and shufffle v2 Migrate from reflection to generic form Note: after migration, old reverse must be removed * Suffle test: remove reflection calls * Reverse test: change name of test --- README.md | 4 ++-- README_zh-CN.md | 4 ++-- slice/slice.go | 33 +++++++++++++++++++-------------- slice/slice_test.go | 21 ++++----------------- 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index b3c8a21..c0a16d3 100644 --- a/README.md +++ b/README.md @@ -409,9 +409,9 @@ func InterfaceSlice(slice interface{}) []interface{} //convert value to interfac func Intersection(slices ...interface{}) interface{} //creates a slice of unique values that included by all slices. func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //insert the element into slice at index. func Map [T any, U any] (slice []T, fn func(index int, t T) U) []U //map lisce, fn signature should be func(int, T). -func ReverseSlice(slice interface{}) //revere slice +func Reverse[T any](slice []T)//revere slice func Reduce[T any](slice []T, fn func(index int, t1, t2 T) T, initial T) T //reduce slice -func Shuffle(slice interface{}) interface{} //creates an slice of shuffled values +func Shuffle[T any](slice []T) []T //creates an slice of shuffled values func SortByField(slice interface{}, field string, sortType ...string) error //sort struct slice by field func Some[T any](slice []T, fn func(index int, t T) bool) bool //return true if any of the values in the list pass the predicate fn function func StringSlice(slice interface{}) []string //convert value to string slice diff --git a/README_zh-CN.md b/README_zh-CN.md index 3038766..ca085b1 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -410,9 +410,9 @@ func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片 func Intersection(slices ...interface{}) interface{} //slice交集,去重 func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置插入value func Map(slice, function interface{}) interface{} //遍历切片, 函数签名:func(index int, value interface{}) interface{} -func ReverseSlice(slice interface{}) //反转切片 +func Reverse[T any](slice []T) //反转切片 func Reduce[T any](slice []T, fn func(index int, t1, t2 T) T, initial T) T //切片reduce操作 -func Shuffle(slice interface{}) interface{} //创建一个被打乱值的切片 +func Shuffle[T any](slice []T) []T //创建一个被打乱值的切片 func Some[T any](slice []T, fn func(index int, t T) bool) bool //slice中任意一个元素都符合函数条件时返回true, 否则返回false. func SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序 func StringSlice(slice interface{}) []string //转为string切片 diff --git a/slice/slice.go b/slice/slice.go index 34bc342..59b2f2b 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -504,26 +504,22 @@ func Intersection[T comparable](slices ...[]T) []T { return Unique(res) } -// ReverseSlice return slice of element order is reversed to the given slice -func ReverseSlice(slice interface{}) { - sv := sliceValue(slice) - swp := reflect.Swapper(sv.Interface()) - for i, j := 0, sv.Len()-1; i < j; i, j = i+1, j-1 { - swp(i, j) +// Reverse return slice of element order is reversed to the given slice +func Reverse[T any](slice []T) { + for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 { + slice[i], slice[j] = slice[j], slice[i] } } // Shuffle creates an slice of shuffled values -func Shuffle(slice interface{}) interface{} { - sv := sliceValue(slice) - length := sv.Len() +func Shuffle[T any](slice []T) []T { - res := reflect.MakeSlice(sv.Type(), length, length) - for i, v := range rand.Perm(length) { - res.Index(i).Set(sv.Index(v)) + res := make([]T, len(slice)) + for i, v := range rand.Perm(len(slice)) { + res[i] = slice[v] } - return res.Interface() + return res } // SortByField return sorted slice by field @@ -576,11 +572,20 @@ func SortByField(slice interface{}, field string, sortType ...string) error { }) if sortType[0] == "desc" { - ReverseSlice(slice) + reverseSlice(slice) } return nil } +// todo remove after migration +func reverseSlice(slice interface{}) { + sv := sliceValue(slice) + swp := reflect.Swapper(sv.Interface()) + for i, j := 0, sv.Len()-1; i < j; i, j = i+1, j-1 { + swp(i, j) + } +} + // Without creates a slice excluding all given values func Without(slice interface{}, values ...interface{}) interface{} { sv := sliceValue(slice) diff --git a/slice/slice_test.go b/slice/slice_test.go index 899eb2e..a252723 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -1,7 +1,6 @@ package slice import ( - "reflect" "testing" "github.com/duke-git/lancet/internal" @@ -398,15 +397,15 @@ func TestIntersection(t *testing.T) { } } -func TestReverseSlice(t *testing.T) { +func TestReverse(t *testing.T) { assert := internal.NewAssert(t, "TestIntersection") s1 := []int{1, 2, 3, 4, 5} - ReverseSlice(s1) + Reverse(s1) assert.Equal([]int{5, 4, 3, 2, 1}, s1) s2 := []string{"a", "b", "c", "d", "e"} - ReverseSlice(s2) + Reverse(s2) assert.Equal([]string{"e", "d", "c", "b", "a"}, s2) } @@ -457,17 +456,5 @@ func TestShuffle(t *testing.T) { res := Shuffle(s) t.Log("Shuffle result: ", res) - assert.Equal(reflect.TypeOf(s), reflect.TypeOf(res)) - - rv := reflect.ValueOf(res) - assert.Equal(5, rv.Len()) - - assert.Equal(true, rv.Kind() == reflect.Slice) - assert.Equal(true, rv.Type().Elem().Kind() == reflect.Int) - - // assert.Equal(true, Contain(res, 1)) - // assert.Equal(true, Contain(res, 2)) - // assert.Equal(true, Contain(res, 3)) - // assert.Equal(true, Contain(res, 4)) - // assert.Equal(true, Contain(res, 5)) + assert.Equal(5, len(res)) }