mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
feat: add UniqueByComparator
This commit is contained in:
@@ -808,6 +808,30 @@ func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UniqueByComparator removes duplicate elements from the input slice using the provided comparator function.
|
||||||
|
// The function maintains the order of the elements.
|
||||||
|
// Play: todo
|
||||||
|
func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T {
|
||||||
|
result := make([]T, 0, len(slice))
|
||||||
|
seen := make([]T, 0, len(slice))
|
||||||
|
|
||||||
|
for _, item := range slice {
|
||||||
|
duplicate := false
|
||||||
|
for _, seenItem := range seen {
|
||||||
|
if comparator(item, seenItem) {
|
||||||
|
duplicate = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !duplicate {
|
||||||
|
seen = append(seen, item)
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// UniqueByField remove duplicate elements in struct slice by struct field.
|
// UniqueByField remove duplicate elements in struct slice by struct field.
|
||||||
// Play: https://go.dev/play/p/6cifcZSPIGu
|
// Play: https://go.dev/play/p/6cifcZSPIGu
|
||||||
func UniqueByField[T any](slice []T, field string) ([]T, error) {
|
func UniqueByField[T any](slice []T, field string) ([]T, error) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleContain() {
|
func ExampleContain() {
|
||||||
@@ -780,6 +781,23 @@ func ExampleUniqueBy() {
|
|||||||
// [1 2 3]
|
// [1 2 3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleUniqueByComparator() {
|
||||||
|
uniqueNums := UniqueByComparator([]int{1, 2, 3, 1, 2, 4, 5, 6, 4}, func(item int, other int) bool {
|
||||||
|
return item == other
|
||||||
|
})
|
||||||
|
|
||||||
|
caseInsensitiveStrings := UniqueByComparator([]string{"apple", "banana", "Apple", "cherry", "Banana", "date"}, func(item string, other string) bool {
|
||||||
|
return strings.ToLower(item) == strings.ToLower(other)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(uniqueNums)
|
||||||
|
fmt.Println(caseInsensitiveStrings)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
// [apple banana cherry date]
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleUniqueByField() {
|
func ExampleUniqueByField() {
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
@@ -764,6 +765,58 @@ func TestUniqueByField(t *testing.T) {
|
|||||||
}, uniqueUsers)
|
}, uniqueUsers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUniqueByComparator(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestUniqueByComparator")
|
||||||
|
|
||||||
|
t.Run("equal comparison", func(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 1, 2, 4, 5, 6, 4, 7}
|
||||||
|
comparator := func(item int, other int) bool {
|
||||||
|
return item == other
|
||||||
|
}
|
||||||
|
result := UniqueByComparator(nums, comparator)
|
||||||
|
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7}, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unique struct slice by field", func(t *testing.T) {
|
||||||
|
type student struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
}
|
||||||
|
|
||||||
|
students := []student{
|
||||||
|
{Name: "a", Age: 11},
|
||||||
|
{Name: "b", Age: 12},
|
||||||
|
{Name: "a", Age: 13},
|
||||||
|
{Name: "c", Age: 14},
|
||||||
|
}
|
||||||
|
|
||||||
|
comparator := func(item, other student) bool { return item.Name == other.Name }
|
||||||
|
|
||||||
|
result := UniqueByComparator(students, comparator)
|
||||||
|
|
||||||
|
assert.Equal([]student{
|
||||||
|
{Name: "a", Age: 11},
|
||||||
|
{Name: "b", Age: 12},
|
||||||
|
{Name: "c", Age: 14},
|
||||||
|
}, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("case-insensitive string comparison", func(t *testing.T) {
|
||||||
|
stringSlice := []string{"apple", "banana", "Apple", "cherry", "Banana", "date"}
|
||||||
|
caseInsensitiveComparator := func(item, other string) bool {
|
||||||
|
return strings.ToLower(item) == strings.ToLower(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := UniqueByComparator(stringSlice, caseInsensitiveComparator)
|
||||||
|
|
||||||
|
assert.Equal([]string{"apple", "banana", "cherry", "date"}, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnion(t *testing.T) {
|
func TestUnion(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user