diff --git a/README.md b/README.md index 58ec205..0a0f7c1 100644 --- a/README.md +++ b/README.md @@ -1416,7 +1416,7 @@ import "github.com/duke-git/lancet/v2/slice" - **Unique** : remove duplicate elements in slice. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Unique)] [[play](https://go.dev/play/p/AXw0R3ZTE6a)] -- **UniqueBy** : call iteratee func with every item of slice, then remove duplicated. +- **UniqueBy** : remove duplicate elements from the input slice based on the values returned by the iteratee function. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueBy)] [[play](https://go.dev/play/p/UR323iZLDpv)] - **UniqueByField** : remove duplicate elements in struct slice by struct field. diff --git a/README_zh-CN.md b/README_zh-CN.md index 90417e6..2ba0936 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -1417,7 +1417,7 @@ import "github.com/duke-git/lancet/v2/slice" - **Unique** : 删除切片中的重复元素。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Unique)] [[play](https://go.dev/play/p/AXw0R3ZTE6a)] -- **UniqueBy** : 对切片的每个元素调用 iteratee 函数,然后删除重复元素。 +- **UniqueBy** : 根据迭代函数返回的值,从输入切片中移除重复元素。此函数保持元素的顺序。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueBy)] [[play](https://go.dev/play/p/UR323iZLDpv)] - **UniqueByField** : 根据struct字段对struct切片去重复。 diff --git a/docs/api/packages/slice.md b/docs/api/packages/slice.md index aaff9fb..b0c614a 100644 --- a/docs/api/packages/slice.md +++ b/docs/api/packages/slice.md @@ -2284,12 +2284,12 @@ func main() { ### UniqueBy -
对切片的每个元素调用iteratee函数,然后删除重复元素
+根据迭代函数返回的值,从输入切片中移除重复元素。此函数保持元素的顺序。
函数签名: ```go -func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T +func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T ``` 示例:[运行](https://go.dev/play/p/UR323iZLDpv) @@ -2309,7 +2309,7 @@ func main() { fmt.Println(result) // Output: - // [1 2 0] + // [1 2 3] } ``` diff --git a/docs/en/api/packages/slice.md b/docs/en/api/packages/slice.md index 858bdbe..c1dc649 100644 --- a/docs/en/api/packages/slice.md +++ b/docs/en/api/packages/slice.md @@ -2282,12 +2282,12 @@ func main() { ### UniqueBy -Call iteratee func with every item of slice, then remove duplicated.
+Removes duplicate elements from the input slice based on the values returned by the iteratee function. this function maintains the order of the elements.
Signature: ```go -func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T +func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T ``` Example:[Run](https://go.dev/play/p/UR323iZLDpv) @@ -2307,7 +2307,7 @@ func main() { fmt.Println(result) // Output: - // [1 2 0] + // [1 2 3] } ``` diff --git a/slice/slice.go b/slice/slice.go index ffc5312..62cd83c 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -783,17 +783,25 @@ func Unique[T comparable](slice []T) []T { return result } -// UniqueBy call iteratee func with every item of slice, then remove duplicated. -// Play: https://go.dev/play/p/UR323iZLDpv -func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T { - result := []T{} +// UniqueBy removes duplicate elements from the input slice based on the values returned by the iteratee function. +// The function maintains the order of the elements. +// Play: todo +func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T { + result := make([]T, 0, len(slice)) + seen := make(map[U]struct{}, len(slice)) - for _, v := range slice { - val := iteratee(v) - result = append(result, val) + for i := range slice { + key := iteratee(slice[i]) + if _, ok := seen[key]; ok { + continue + } + + seen[key] = struct{}{} + + result = append(result, slice[i]) } - return Unique(result) + return result } // UniqueByField remove duplicate elements in struct slice by struct field. diff --git a/slice/slice_example_test.go b/slice/slice_example_test.go index 9bd9803..db8d0b5 100644 --- a/slice/slice_example_test.go +++ b/slice/slice_example_test.go @@ -777,7 +777,7 @@ func ExampleUniqueBy() { fmt.Println(result) // Output: - // [1 2 0] + // [1 2 3] } func ExampleUniqueByField() { diff --git a/slice/slice_test.go b/slice/slice_test.go index 7a543f0..d03fb9c 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -733,7 +733,8 @@ func TestUniqueBy(t *testing.T) { actual := UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int { return val % 4 }) - assert.Equal([]int{1, 2, 3, 0}, actual) + + assert.Equal([]int{1, 2, 3, 4}, actual) } func TestUniqueByField(t *testing.T) {