From e33476ea5ca3a00a89d3cafe87156a332ac244e2 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sat, 5 Sep 2026 09:23:54 +1000 Subject: [PATCH] Added FilterMap --- moslice/filter.go | 19 +++++++++++++++++++ moslice/filter_test.go | 24 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/moslice/filter.go b/moslice/filter.go index cd3bbbb..07900e8 100644 --- a/moslice/filter.go +++ b/moslice/filter.go @@ -16,3 +16,22 @@ func Filter[T any](ts []T, predicate func(t T) bool) []T { } return filteredTs } + +// FilterMap returns a mapped slice containing all the elements of ts for which the passed in +// predicate returns true. If no items match the predicate, the function will return +// an empty slice. If ts is nil, the function will also return nil. +func FilterMap[T, U any](ts []T, predicate func(t T) (U, bool)) []U { + if ts == nil { + return nil + } + + filteredUs := make([]U, 0) + for _, t := range ts { + u, ok := predicate(t) + if !ok { + continue + } + filteredUs = append(filteredUs, u) + } + return filteredUs +} diff --git a/moslice/filter_test.go b/moslice/filter_test.go index 1d4ae28..f77a02f 100644 --- a/moslice/filter_test.go +++ b/moslice/filter_test.go @@ -1,10 +1,12 @@ package moslice_test import ( - "lmika.dev/pkg/modash/moslice" + "fmt" "strings" "testing" + "lmika.dev/pkg/modash/moslice" + "github.com/stretchr/testify/assert" ) @@ -27,3 +29,23 @@ func TestFilter(t *testing.T) { assert.Equal(t, []int{}, moslice.Filter([]int{}, func(x int) bool { return x%2 == 0 })) }) } + +func TestFilterMap(t *testing.T) { + var ( + ints = []int{1, 2, 3, 4, 5} + strs = []string{"foo", "bar", "baz"} + ) + + t.Run("should filter items matching the predicate", func(t *testing.T) { + assert.Equal(t, []string{"2", "4"}, moslice.FilterMap(ints, func(x int) (string, bool) { return fmt.Sprint(x), x%2 == 0 })) + assert.Equal(t, []int{3, 3}, moslice.FilterMap(strs, func(x string) (int, bool) { return len(x), strings.Contains(x, "b") })) + }) + + t.Run("should moslice nil if the passed in slice is nil", func(t *testing.T) { + assert.Nil(t, moslice.FilterMap(nil, func(x int) (string, bool) { return fmt.Sprint(x), x%2 == 0 })) + }) + + t.Run("should return empty slice if the passed in slice is empty slice", func(t *testing.T) { + assert.Equal(t, []string{}, moslice.FilterMap([]int{}, func(x int) (string, bool) { return fmt.Sprint(x), x%2 == 0 })) + }) +}