Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions intersect.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ func Intersect[T comparable, Slice ~[]T](list1 Slice, list2 Slice) Slice {
return result
}

// 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 element absent of list2.
// The second value is the collection of element absent of list1.
Expand Down
41 changes: 41 additions & 0 deletions intersect_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lo

import (
"strconv"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -194,6 +195,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)
Expand Down
Loading