/
distinct_by.go
78 lines (61 loc) · 1.77 KB
/
distinct_by.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package goe
import "github.com/EscanBE/go-ienumerable/goe/comparers"
func (src *enumerable[T]) DistinctBy(keySelector KeySelector[T], optionalEqualsFunc OptionalEqualsFunc[any]) IEnumerable[T] {
src.assertSrcNonNil()
assertKeySelectorNonNil(keySelector)
unique := distinctByKeySelector(copySlice(src.data), keySelector, optionalEqualsFunc)
return src.copyExceptData().withData(unique)
}
type distinctElementHolder struct {
elementIndex int
key any
}
func distinctByKeySelector[T any](data []T, requiredKeySelector KeySelector[T], optionalEqualityComparer OptionalEqualsFunc[any]) []T {
if requiredKeySelector == nil {
panic(getErrorKeySelectorNotNil())
}
var equalityComparer EqualsFunc[any]
if optionalEqualityComparer != nil {
equalityComparer = EqualsFunc[any](optionalEqualityComparer)
}
holders := make([]distinctElementHolder, len(data))
for i, d := range data {
holders[i] = distinctElementHolder{
elementIndex: i,
key: requiredKeySelector(d),
}
if equalityComparer == nil {
comparer, found := comparers.TryGetDefaultComparerFromValue(holders[i].key)
if found {
equalityComparer = func(v1, v2 any) bool {
return comparer.CompareAny(v1, v2) == 0
}
}
}
}
if equalityComparer == nil {
panic(getErrorFailedCompare2ElementsInArray())
}
if len(data) < 1 {
return data
}
uniqueSet := []distinctElementHolder{holders[0]}
for i1 := 1; i1 < len(data); i1++ {
ele := holders[i1]
var exists bool
for _, uniq := range uniqueSet {
if equalityComparer(ele.key, uniq.key) {
exists = true
break
}
}
if !exists {
uniqueSet = append(uniqueSet, ele)
}
}
uniqueResult := make([]T, len(uniqueSet))
for i, h := range uniqueSet {
uniqueResult[i] = data[h.elementIndex]
}
return uniqueResult
}