mirror of
https://github.com/samber/lo.git
synced 2026-04-22 23:47:11 +08:00
Feature/intersect by (#653)
* Update README.md
Fixed the error in the usage example of lo.Latest in readme.md
use []time.Time{…} (value of type []time.Time) as time.Time value in argument to lo.Latest
* Update README.md
* feature: add Mode function with tests and documentation
* feat: Add IntersectBy function and tests, supporting intersection by custom key sets
---------
Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
This commit is contained in:
@@ -170,6 +170,27 @@ func Intersect[T comparable, Slice ~[]T](lists ...Slice) Slice {
|
||||
return Slice{}
|
||||
}
|
||||
|
||||
// IntersectBy returns the intersection between two collections using a custom key selector function.
|
||||
// It preserves the order of elements from the second list (list2).
|
||||
func IntersectBy[T any, K comparable, Slice ~[]T](list1 Slice, list2 Slice, iteratee func(T) K) Slice {
|
||||
result := make(Slice, 0)
|
||||
seen := make(map[K]struct{})
|
||||
|
||||
for _, item := range list1 {
|
||||
key := iteratee(item)
|
||||
seen[key] = struct{}{}
|
||||
}
|
||||
|
||||
for _, item := range list2 {
|
||||
key := iteratee(item)
|
||||
if _, exists := seen[key]; exists {
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Difference returns the difference between two collections.
|
||||
// The first value is the collection of elements absent from list2.
|
||||
// The second value is the collection of elements absent from list1.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lo
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -204,6 +205,46 @@ func TestIntersect(t *testing.T) {
|
||||
is.IsType(nonempty, allStrings, "type preserved")
|
||||
}
|
||||
|
||||
func TestIntersectBy(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
}
|
||||
|
||||
list1 := []User{
|
||||
{ID: 1, Name: "Alice"},
|
||||
{ID: 2, Name: "Bob"},
|
||||
{ID: 3, Name: "Charlie"},
|
||||
}
|
||||
|
||||
list2 := []User{
|
||||
{ID: 2, Name: "Robert"},
|
||||
{ID: 3, Name: "Charlie"},
|
||||
{ID: 4, Name: "Alice"},
|
||||
}
|
||||
|
||||
intersectByID := IntersectBy(list1, list2, func(u User) int {
|
||||
return u.ID
|
||||
})
|
||||
is.Equal(intersectByID, []User{{ID: 2, Name: "Robert"}, {ID: 3, Name: "Charlie"}})
|
||||
// output: [{2 Robert} {3 Charlie}]
|
||||
|
||||
intersectByName := IntersectBy(list1, list2, func(u User) string {
|
||||
return u.Name
|
||||
})
|
||||
is.Equal(intersectByName, []User{{ID: 3, Name: "Charlie"}, {ID: 4, Name: "Alice"}})
|
||||
// output: [{3 Charlie} {4 Alice}]
|
||||
|
||||
intersectByIDAndName := IntersectBy(list1, list2, func(u User) string {
|
||||
return strconv.Itoa(u.ID) + u.Name
|
||||
})
|
||||
is.Equal(intersectByIDAndName, []User{{ID: 3, Name: "Charlie"}})
|
||||
// output: [{3 Charlie}]
|
||||
}
|
||||
|
||||
func TestDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
is := assert.New(t)
|
||||
|
||||
Reference in New Issue
Block a user