---
name: ElementsMatchBy
slug: elementsmatchby
sourceRef: it/intersect.go#L183
category: it
subCategory: intersect
signatures:
  - "func ElementsMatchBy[T any, K comparable](list1, list2 iter.Seq[T], transform func(item T) K) bool"
playUrl: "https://go.dev/play/p/I3vFrmQo43E"
variantHelpers:
  - it#intersect#elementsmatchby
similarHelpers:
  - core#slice#elementsmatchby
position: 730
---

Returns true if lists contain the same set of elements' keys (including empty set).

If there are duplicate keys, the number of occurrences in each list should match.
The order of elements is not checked.
Will iterate through each sequence before returning and allocate a map large enough to hold all distinct transformed elements.
Long heterogeneous input sequences can cause excessive memory usage.

Examples:

```go
// Match people by age (ignoring names)
type Person struct {
    Name string
    Age  int
}
people1 := it.Slice([]Person{
    {Name: "Alice", Age: 30},
    {Name: "Bob", Age: 25},
    {Name: "Charlie", Age: 35},
})
people2 := it.Slice([]Person{
    {Name: "David", Age: 35},
    {Name: "Eve", Age: 25},
    {Name: "Frank", Age: 30},
})
match := it.ElementsMatchBy(people1, people2, func(p Person) int { return p.Age })
// match: true (both have ages 25, 30, 35)

// Match by string length
words1 := it.Slice([]string{"hello", "world", "go", "lang"})
words2 := it.Slice([]string{"short", "longer", "golang", "python"})
match = it.ElementsMatchBy(words1, words2, func(s string) int { return len(s) })
// match: false (lengths: 5,5,2,4 vs 6,6,6,6)

// Match by first character
items1 := it.Slice([]string{"apple", "apricot", "banana", "blueberry"})
items2 := it.Slice([]string{"ant", "anchor", "boat", "berry"})
match = it.ElementsMatchBy(items1, items2, func(s string) byte { return s[0] })
// match: true (both start with a, a, b, b)

// Match emails by domain
type Email struct {
    Address string
}
emails1 := it.Slice([]Email{
    {Address: "user1@example.com"},
    {Address: "user2@gmail.com"},
    {Address: "user3@example.com"},
})
emails2 := it.Slice([]Email{
    {Address: "different@gmail.com"},
    {Address: "another@example.com"},
    {Address: "third@example.com"},
})
match = it.ElementsMatchBy(emails1, emails2, func(e Email) string {
    parts := strings.Split(e.Address, "@")
    if len(parts) > 1 {
        return parts[1]
    }
    return ""
})
// match: true (both have domains: example.com, gmail.com, example.com)

// Match by modulo operation
numbers1 := it.Slice([]int{1, 2, 3, 4, 5, 6})
numbers2 := it.Slice([]int{7, 8, 9, 10, 11, 12})
match = it.ElementsMatchBy(numbers1, numbers2, func(n int) int { return n % 3 })
// match: true (remainders: 1,2,0,1,2,0 vs 1,2,0,1,2,0)

// Match by case-insensitive strings
strings1 := it.Slice([]string{"Hello", "World", "GO"})
strings2 := it.Slice([]string{"hello", "world", "go"})
match = it.ElementsMatchBy(strings1, strings2, func(s string) string { return strings.ToLower(s) })
// match: true

// Match orders by customer ID (ignoring order details)
type Order struct {
    ID         string
    CustomerID string
    ProductID  string
}
orders1 := it.Slice([]Order{
    {ID: "1", CustomerID: "A", ProductID: "X"},
    {ID: "2", CustomerID: "B", ProductID: "Y"},
    {ID: "3", CustomerID: "A", ProductID: "Z"},
})
orders2 := it.Slice([]Order{
    {ID: "4", CustomerID: "B", ProductID: "W"},
    {ID: "5", CustomerID: "A", ProductID: "V"},
    {ID: "6", CustomerID: "A", ProductID: "U"},
})
match = it.ElementsMatchBy(orders1, orders2, func(o Order) string { return o.CustomerID })
// match: true (both have customer IDs: A, B, A)

// Match dates by year-month (ignoring day)
import "time"
dates1 := it.Slice([]time.Time{
    time.Date(2023, 1, 15, 0, 0, 0, 0, time.UTC),
    time.Date(2023, 2, 20, 0, 0, 0, 0, time.UTC),
    time.Date(2023, 1, 25, 0, 0, 0, 0, time.UTC),
})
dates2 := it.Slice([]time.Time{
    time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC),
    time.Date(2023, 2, 10, 0, 0, 0, 0, time.UTC),
    time.Date(2023, 1, 30, 0, 0, 0, 0, time.UTC),
})
match = it.ElementsMatchBy(dates1, dates2, func(t time.Time) string {
    return fmt.Sprintf("%d-%02d", t.Year(), t.Month())
})
// match: true (both have: 2023-01, 2023-02, 2023-01)

// Match by category function
type Product struct {
    Name  string
    Price float64
}
products1 := it.Slice([]Product{
    {Name: "Book", Price: 19.99},
    {Name: "Pen", Price: 1.99},
    {Name: "Laptop", Price: 999.99},
})
products2 := it.Slice([]Product{
    {Name: "Pencil", Price: 0.99},
    {Name: "Phone", Price: 699.99},
    {Name: "Desk", Price: 199.99},
})
match = it.ElementsMatchBy(products1, products2, func(p Product) string {
    if p.Price < 10 {
        return "cheap"
    } else if p.Price < 100 {
        return "medium"
    }
    return "expensive"
})
// match: true (both have: medium, cheap, expensive)

// Match by custom classification
type Student struct {
    Name string
    Age  int
}
students1 := it.Slice([]Student{
    {Name: "Alice", Age: 8},
    {Name: "Bob", Age: 15},
    {Name: "Charlie", Age: 20},
})
students2 := it.Slice([]Student{
    {Name: "Diana", Age: 25},
    {Name: "Eve", Age: 10},
    {Name: "Frank", Age: 12},
})
match = it.ElementsMatchBy(students1, students2, func(s Student) string {
    if s.Age < 12 {
        return "child"
    } else if s.Age < 18 {
        return "teen"
    }
    return "adult"
})
// match: false (students1: child, teen, adult vs students2: adult, child, child)
```