diff --git a/slice/slice.go b/slice/slice.go index 2aa8644..d548851 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -582,6 +582,21 @@ func Unique[T any](slice []T) []T { return res } +// UniqueBy call iteratee func with every item of slice, then remove duplicated. +func UniqueBy[T any](slice []T, iteratee func(item T) T) []T { + if len(slice) == 0 { + return []T{} + } + + var res []T + for _, v := range slice { + val := iteratee(v) + res = append(res, val) + } + + return Unique(res) +} + // Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons. func Union[T any](slices ...[]T) []T { if len(slices) == 0 { diff --git a/slice/slice_test.go b/slice/slice_test.go index 8fcf6df..b42e05c 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -395,6 +395,15 @@ func TestUnique(t *testing.T) { assert.Equal([]string{"a", "b", "c"}, Unique([]string{"a", "a", "b", "c"})) } +func TestUniqueBy(t *testing.T) { + assert := internal.NewAssert(t, "TestUniqueBy") + + actual := UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int { + return val % 4 + }) + assert.Equal([]int{1, 2, 3, 0}, actual) +} + func TestUnion(t *testing.T) { assert := internal.NewAssert(t, "TestUnion")