From 44dad438d9f6eceb46d2cc3f95bf923515b2e974 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Thu, 27 Jun 2024 16:10:05 +0200 Subject: [PATCH] feat: adding FilterReject --- README.md | 13 +++++++++++++ slice.go | 17 +++++++++++++++++ slice_test.go | 23 +++++++++++++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d37ed23..e3c0ae59 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ Supported helpers for slices: - [DropWhile](#dropwhile) - [DropRightWhile](#droprightwhile) - [Reject](#reject) +- [FilterReject](#filterreject) - [Count](#count) - [CountBy](#countby) - [CountValues](#countvalues) @@ -742,6 +743,18 @@ odd := lo.Reject([]int{1, 2, 3, 4}, func(x int, _ int) bool { [[play](https://go.dev/play/p/YkLMODy1WEL)] +### FilterReject + +FilterReject mixes Filter and Reject, this method returns two slices, one for the elements of collection that predicate returns truthy for and one for the elements that predicate does not return truthy for. + +```go +kept, rejected := lo.FilterReject([]int{1, 2, 3, 4}, func(x int, _ int) bool { + return x%2 == 0 +}) +// []int{2, 4} +// []int{1, 3} +``` + ### Count Counts the number of elements in the collection that compare equal to value. diff --git a/slice.go b/slice.go index 4bfed2de..1da55ee1 100644 --- a/slice.go +++ b/slice.go @@ -431,6 +431,23 @@ func Reject[V any](collection []V, predicate func(item V, index int) bool) []V { return result } +// FilterReject mixes Filter and Reject, this method returns two slices, one for the elements of collection that +// predicate returns truthy for and one for the elements that predicate does not return truthy for. +func FilterReject[V any](collection []V, predicate func(V, int) bool) (kept []V, rejected []V) { + kept = make([]V, 0, len(collection)) + rejected = make([]V, 0, len(collection)) + + for i, item := range collection { + if predicate(item, i) { + kept = append(kept, item) + } else { + rejected = append(rejected, item) + } + } + + return kept, rejected +} + // Count counts the number of elements in the collection that compare equal to value. // Play: https://go.dev/play/p/Y3FlK54yveC func Count[T comparable](collection []T, value T) (count int) { diff --git a/slice_test.go b/slice_test.go index 03326a01..a404501f 100644 --- a/slice_test.go +++ b/slice_test.go @@ -388,7 +388,7 @@ func TestAssociate(t *testing.T) { func TestSliceToMap(t *testing.T) { t.Parallel() - + type foo struct { baz string bar int @@ -500,6 +500,25 @@ func TestReject(t *testing.T) { is.Equal(r2, []string{"foo", "bar"}) } +func TestFilterReject(t *testing.T) { + t.Parallel() + is := assert.New(t) + + left1, right1 := FilterReject([]int{1, 2, 3, 4}, func(x int, _ int) bool { + return x%2 == 0 + }) + + is.Equal(left1, []int{2, 4}) + is.Equal(right1, []int{1, 3}) + + left2, right2 := FilterReject([]string{"Smith", "foo", "Domin", "bar", "Olivia"}, func(x string, _ int) bool { + return len(x) > 3 + }) + + is.Equal(left2, []string{"Smith", "Domin", "Olivia"}) + is.Equal(right2, []string{"foo", "bar"}) +} + func TestCount(t *testing.T) { t.Parallel() is := assert.New(t) @@ -626,7 +645,7 @@ func TestSlice(t *testing.T) { out16 := Slice(in, -10, 1) out17 := Slice(in, -1, 3) out18 := Slice(in, -10, 7) - + is.Equal([]int{}, out1) is.Equal([]int{0}, out2) is.Equal([]int{0, 1, 2, 3, 4}, out3)