diff --git a/slice/slice.go b/slice/slice.go index fa7e993..a66cd9d 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -315,6 +315,34 @@ func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool) return &slice[index], true } +// FindLast iterates over elements of slice from end to begin, returning the first one that passes a truth test on function. +// The function signature should be func(index int, value interface{}) bool . +func FindLast(slice, function interface{}) (interface{}, bool) { + sv := sliceValue(slice) + fn := functionValue(function) + + elemType := sv.Type().Elem() + if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) { + panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String()) + } + + index := -1 + for i := sv.Len() - 1; i >= 0; i-- { + flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0] + if flag.Bool() { + index = i + break + } + } + + if index == -1 { + var none interface{} + return none, false + } + + return sv.Index(index).Interface(), true +} + // FlattenDeep flattens slice recursive func FlattenDeep(slice interface{}) interface{} { sv := sliceValue(slice) diff --git a/slice/slice_test.go b/slice/slice_test.go index 16f6a6b..ceaf7a8 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -180,6 +180,20 @@ func TestFindLast(t *testing.T) { assert.Equal(4, *res) } +func TestFindLast(t *testing.T) { + nums := []int{1, 2, 3, 4, 5} + even := func(i, num int) bool { + return num%2 == 0 + } + res, ok := FindLast(nums, even) + if !ok { + t.Fatal("found nothing") + } + + assert := internal.NewAssert(t, "TestFindLast") + assert.Equal(4, res) +} + func TestFindFoundNothing(t *testing.T) { nums := []int{1, 1, 1, 1, 1, 1} findFunc := func(i, num int) bool {