1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35:28 +08:00

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
This commit is contained in:
donutloop
2022-01-10 12:52:23 +01:00
committed by GitHub
parent e9fed34729
commit 24c0d95112
4 changed files with 27 additions and 35 deletions

View File

@@ -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 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 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 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 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 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 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 func StringSlice(slice interface{}) []string //convert value to string slice

View File

@@ -410,9 +410,9 @@ func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
func Intersection(slices ...interface{}) interface{} //slice交集去重 func Intersection(slices ...interface{}) interface{} //slice交集去重
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置插入value 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 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 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 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 SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序
func StringSlice(slice interface{}) []string //转为string切片 func StringSlice(slice interface{}) []string //转为string切片

View File

@@ -504,26 +504,22 @@ func Intersection[T comparable](slices ...[]T) []T {
return Unique(res) return Unique(res)
} }
// ReverseSlice return slice of element order is reversed to the given slice // Reverse return slice of element order is reversed to the given slice
func ReverseSlice(slice interface{}) { func Reverse[T any](slice []T) {
sv := sliceValue(slice) for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
swp := reflect.Swapper(sv.Interface()) slice[i], slice[j] = slice[j], slice[i]
for i, j := 0, sv.Len()-1; i < j; i, j = i+1, j-1 {
swp(i, j)
} }
} }
// Shuffle creates an slice of shuffled values // Shuffle creates an slice of shuffled values
func Shuffle(slice interface{}) interface{} { func Shuffle[T any](slice []T) []T {
sv := sliceValue(slice)
length := sv.Len()
res := reflect.MakeSlice(sv.Type(), length, length) res := make([]T, len(slice))
for i, v := range rand.Perm(length) { for i, v := range rand.Perm(len(slice)) {
res.Index(i).Set(sv.Index(v)) res[i] = slice[v]
} }
return res.Interface() return res
} }
// SortByField return sorted slice by field // SortByField return sorted slice by field
@@ -576,11 +572,20 @@ func SortByField(slice interface{}, field string, sortType ...string) error {
}) })
if sortType[0] == "desc" { if sortType[0] == "desc" {
ReverseSlice(slice) reverseSlice(slice)
} }
return nil 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 // Without creates a slice excluding all given values
func Without(slice interface{}, values ...interface{}) interface{} { func Without(slice interface{}, values ...interface{}) interface{} {
sv := sliceValue(slice) sv := sliceValue(slice)

View File

@@ -1,7 +1,6 @@
package slice package slice
import ( import (
"reflect"
"testing" "testing"
"github.com/duke-git/lancet/internal" "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") assert := internal.NewAssert(t, "TestIntersection")
s1 := []int{1, 2, 3, 4, 5} s1 := []int{1, 2, 3, 4, 5}
ReverseSlice(s1) Reverse(s1)
assert.Equal([]int{5, 4, 3, 2, 1}, s1) assert.Equal([]int{5, 4, 3, 2, 1}, s1)
s2 := []string{"a", "b", "c", "d", "e"} s2 := []string{"a", "b", "c", "d", "e"}
ReverseSlice(s2) Reverse(s2)
assert.Equal([]string{"e", "d", "c", "b", "a"}, s2) assert.Equal([]string{"e", "d", "c", "b", "a"}, s2)
} }
@@ -457,17 +456,5 @@ func TestShuffle(t *testing.T) {
res := Shuffle(s) res := Shuffle(s)
t.Log("Shuffle result: ", res) t.Log("Shuffle result: ", res)
assert.Equal(reflect.TypeOf(s), reflect.TypeOf(res)) assert.Equal(5, len(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))
} }