From 14bc08c6d6c6865c90f4ffe156683c89d0f71a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=87=95=E5=BD=92=E6=9D=A5?= Date: Mon, 17 Apr 2023 20:11:56 +0800 Subject: [PATCH] feat: add FindBy that a result will be without unrefrence #88 (#90) feat: add example for FindBy chore: reduce code duplication --- slice/slice.go | 38 +++++++++++++++++++++++-------------- slice/slice_example_test.go | 17 +++++++++++++++++ slice/slice_test.go | 19 +++++++++++++++++++ 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/slice/slice.go b/slice/slice.go index 39ea647..5837575 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -319,27 +319,17 @@ func GroupWith[T any, U comparable](slice []T, iteratee func(item T) U) map[U][] // Find iterates over elements of slice, returning the first one that passes a truth test on predicate function. // If return T is nil then no items matched the predicate func. // Play: https://go.dev/play/p/CBKeBoHVLgq +// Deprecated func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) { - index := -1 - - for i, v := range slice { - if predicate(i, v) { - index = i - break - } - } - - if index == -1 { - return nil, false - } - - return &slice[index], true + v, ok := FindBy(slice, predicate) + return &v, ok } // FindLast iterates over elements of slice from end to begin, // return the first one that passes a truth test on predicate function. // If return T is nil then no items matched the predicate func. // Play: https://go.dev/play/p/FFDPV_j7URd +// Deprecated func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) { index := -1 @@ -357,6 +347,26 @@ func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, boo return &slice[index], true } +// FindBy iterates over elements of slice, returning the first one that passes a truth test on predicate function. +// If return T is nil or zero value then no items matched the predicate func. +// In contrast to Find or FindLast, its return value no longer requires dereferencing +func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) { + index := -1 + + for i, v := range slice { + if predicate(i, v) { + index = i + break + } + } + + if index == -1 { + return v, false + } + + return slice[index], true +} + // Flatten flattens slice with one level. // Play: https://go.dev/play/p/hYa3cBEevtm func Flatten(slice any) any { diff --git a/slice/slice_example_test.go b/slice/slice_example_test.go index d8d3a67..347eb93 100644 --- a/slice/slice_example_test.go +++ b/slice/slice_example_test.go @@ -341,6 +341,23 @@ func ExampleFindLast() { // true } +func ExampleFindBy() { + nums := []int{1, 2, 3, 4, 5} + + isEven := func(i, num int) bool { + return num%2 == 0 + } + + result, ok := FindBy(nums, isEven) + + fmt.Println(result) + fmt.Println(ok) + + // Output: + // 2 + // true +} + func ExampleFlatten() { arrs := [][][]string{{{"a", "b"}}, {{"c", "d"}}} diff --git a/slice/slice_test.go b/slice/slice_test.go index 805403b..c717e03 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -249,6 +249,25 @@ func TestFind(t *testing.T) { assert.Equal(2, *res) } +func TestFindBy(t *testing.T) { + assert := internal.NewAssert(t, "TestFindBy") + + nums := []int{1, 2, 3, 4, 5} + even := func(i, num int) bool { + return num%2 == 0 + } + res, ok := FindBy(nums, even) + if !ok { + t.Fatal("found nothing") + } + assert.Equal(2, res) + + res, ok = FindBy(nums, func(_ int, v int) bool { + return v == 6 + }) + assert.Equal(res == 0 && ok == false, true) +} + func TestFindLast(t *testing.T) { nums := []int{1, 2, 3, 4, 5} even := func(i, num int) bool {