Skip to content

Commit 4a43ff6

Browse files
senagosamber
andauthored
Add ElementsMatch, ElementsMatchBy (#589)
* Add ElementsMatch, ElementsMatchBy * Update intersect.go * Update README.md --------- Co-authored-by: Samuel Berthe <[email protected]>
1 parent 0bc568a commit 4a43ff6

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ Supported intersection helpers:
221221
- [WithoutBy](#withoutby)
222222
- [WithoutEmpty](#withoutempty)
223223
- [WithoutNth](#withoutnth)
224+
- [ElementsMatch](#ElementsMatch)
225+
- [ElementsMatchBy](#ElementsMatchBy)
224226

225227
Supported search helpers:
226228

@@ -2400,6 +2402,36 @@ subset := lo.WithoutNth([]int{-2, -1, 0, 1, 2}, 3, -42, 1)
24002402
// []int{-2, 0, 2}
24012403
```
24022404

2405+
### ElementsMatch
2406+
2407+
Returns true if lists contain the same set of elements (including empty set).
2408+
2409+
If there are duplicate elements, the number of appearances of each of them in both lists should match.
2410+
2411+
The order of elements is not checked.
2412+
2413+
```go
2414+
b := lo.ElementsMatch([]int{1, 1, 2}, []int{2, 1, 1})
2415+
// true
2416+
```
2417+
2418+
### ElementsMatchBy
2419+
2420+
Returns true if lists contain the same set of elements' keys (including empty set).
2421+
2422+
If there are duplicate keys, the number of appearances of each of them in both lists should match.
2423+
2424+
The order of elements is not checked.
2425+
2426+
```go
2427+
b := lo.ElementsMatchBy(
2428+
[]someType{a, b},
2429+
[]someType{b, a},
2430+
func(item someType) string { return item.ID() },
2431+
)
2432+
// true
2433+
```
2434+
24032435
### IndexOf
24042436

24052437
Returns the index at which the first occurrence of a value is found in an array or return -1 if the value cannot be found.

intersect.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,41 @@ func WithoutNth[T comparable, Slice ~[]T](collection Slice, nths ...int) Slice {
225225

226226
return result
227227
}
228+
229+
// ElementsMatch returns true if lists contain the same set of elements (including empty set).
230+
// If there are duplicate elements, the number of appearances of each of them in both lists should match.
231+
// The order of elements is not checked.
232+
func ElementsMatch[T comparable, Slice ~[]T](list1 Slice, list2 Slice) bool {
233+
return ElementsMatchBy(list1, list2, func(item T) T { return item })
234+
}
235+
236+
// ElementsMatchBy returns true if lists contain the same set of elements' keys (including empty set).
237+
// If there are duplicate keys, the number of appearances of each of them in both lists should match.
238+
// The order of elements is not checked.
239+
func ElementsMatchBy[T any, K comparable](list1 []T, list2 []T, iteratee func(item T) K) bool {
240+
if len(list1) != len(list2) {
241+
return false
242+
}
243+
244+
if len(list1) == 0 {
245+
return true
246+
}
247+
248+
counters := make(map[K]int, len(list1))
249+
250+
for _, el := range list1 {
251+
counters[iteratee(el)]++
252+
}
253+
254+
for _, el := range list2 {
255+
counters[iteratee(el)]--
256+
}
257+
258+
for _, count := range counters {
259+
if count != 0 {
260+
return false
261+
}
262+
}
263+
264+
return true
265+
}

intersect_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,34 @@ func TestWithoutNth(t *testing.T) {
330330
nonempty := WithoutNth(allStrings)
331331
is.IsType(nonempty, allStrings, "type preserved")
332332
}
333+
334+
func TestElementsMatch(t *testing.T) {
335+
t.Parallel()
336+
is := assert.New(t)
337+
338+
is.False(ElementsMatch([]int{}, []int{1}))
339+
is.False(ElementsMatch([]int{1}, []int{2}))
340+
is.False(ElementsMatch([]int{1}, []int{1, 2}))
341+
is.False(ElementsMatch([]int{1, 1, 2}, []int{2, 2, 1}))
342+
343+
is.True(ElementsMatch([]int{}, nil))
344+
is.True(ElementsMatch([]int{1}, []int{1}))
345+
is.True(ElementsMatch([]int{1, 1}, []int{1, 1}))
346+
is.True(ElementsMatch([]int{1, 2}, []int{2, 1}))
347+
is.True(ElementsMatch([]int{1, 1, 2}, []int{1, 2, 1}))
348+
}
349+
350+
func TestElementsMatchBy(t *testing.T) {
351+
t.Parallel()
352+
is := assert.New(t)
353+
354+
type someType struct {
355+
key string
356+
}
357+
358+
is.True(ElementsMatchBy(
359+
[]someType{{key: "a"}, {key: "b"}},
360+
[]someType{{key: "b"}, {key: "a"}},
361+
func(item someType) string { return item.key },
362+
))
363+
}

0 commit comments

Comments
 (0)