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

feat: add FlattenDeep func

This commit is contained in:
dudaodong
2022-01-01 18:14:35 +08:00
parent b42aac53b3
commit 042a00296f
3 changed files with 53 additions and 7 deletions

View File

@@ -190,6 +190,30 @@ func Find(slice, function interface{}) interface{} {
return sv.Index(index).Interface() return sv.Index(index).Interface()
} }
// FlattenDeep flattens slice recursive
func FlattenDeep(slice interface{}) interface{} {
sv := sliceValue(slice)
st := sliceElemType(sv.Type())
tmp := reflect.MakeSlice(reflect.SliceOf(st), 0, 0)
res := flattenRecursive(sv, tmp)
return res.Interface()
}
func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
for i := 0; i < value.Len(); i++ {
item := value.Index(i)
kind := item.Kind()
if kind == reflect.Slice {
result = flattenRecursive(item, result)
} else {
result = reflect.Append(result, item)
}
}
return result
}
// Map creates an slice of values by running each element of `slice` thru `function`. // Map creates an slice of values by running each element of `slice` thru `function`.
// The function signature should be func(index int, value interface{}) interface{}. // The function signature should be func(index int, value interface{}) interface{}.
func Map(slice, function interface{}) interface{} { func Map(slice, function interface{}) interface{} {
@@ -521,9 +545,9 @@ func Intersection(slices ...interface{}) interface{} {
// ReverseSlice return slice of element order is reversed to the given slice // ReverseSlice return slice of element order is reversed to the given slice
func ReverseSlice(slice interface{}) { func ReverseSlice(slice interface{}) {
v := sliceValue(slice) sv := sliceValue(slice)
swp := reflect.Swapper(v.Interface()) swp := reflect.Swapper(sv.Interface())
for i, j := 0, v.Len()-1; i < j; i, j = i+1, j-1 { for i, j := 0, sv.Len()-1; i < j; i, j = i+1, j-1 {
swp(i, j) swp(i, j)
} }
} }
@@ -532,8 +556,8 @@ func ReverseSlice(slice interface{}) {
// Slice element should be struct, field type should be int, uint, string, or bool // Slice element should be struct, field type should be int, uint, string, or bool
// default sortType is ascending (asc), if descending order, set sortType to desc // default sortType is ascending (asc), if descending order, set sortType to desc
func SortByField(slice interface{}, field string, sortType ...string) error { func SortByField(slice interface{}, field string, sortType ...string) error {
v := sliceValue(slice) sv := sliceValue(slice)
t := v.Type().Elem() t := sv.Type().Elem()
if t.Kind() == reflect.Ptr { if t.Kind() == reflect.Ptr {
t = t.Elem() t = t.Elem()
@@ -566,8 +590,8 @@ func SortByField(slice interface{}, field string, sortType ...string) error {
} }
sort.Slice(slice, func(i, j int) bool { sort.Slice(slice, func(i, j int) bool {
a := v.Index(i) a := sv.Index(i)
b := v.Index(j) b := sv.Index(j)
if t.Kind() == reflect.Ptr { if t.Kind() == reflect.Ptr {
a = a.Elem() a = a.Elem()
b = b.Elem() b = b.Elem()

View File

@@ -173,6 +173,17 @@ func TestFind(t *testing.T) {
} }
} }
func TestFlattenDeep(t *testing.T) {
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
expected := []string{"a", "b", "c", "d"}
res := FlattenDeep(input)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "FlattenDeep", input, expected, res)
t.FailNow()
}
}
func TestMap(t *testing.T) { func TestMap(t *testing.T) {
s1 := []int{1, 2, 3, 4} s1 := []int{1, 2, 3, 4}
multiplyTwo := func(i, num int) int { multiplyTwo := func(i, num int) int {

View File

@@ -52,3 +52,14 @@ func checkSliceCallbackFuncSignature(fn reflect.Value, types ...reflect.Type) bo
} }
return true return true
} }
// sliceElemType get slice element type
func sliceElemType(reflectType reflect.Type) reflect.Type {
for {
if reflectType.Kind() != reflect.Slice {
return reflectType
}
reflectType = reflectType.Elem()
}
}