-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
groupby.go
60 lines (53 loc) · 1.19 KB
/
groupby.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
package linq
// Grouping represents a collection of objects that have a common key.
type Grouping[T any, K comparable] struct {
Enumerable Enumerable[T]
Key K
}
type groupByEnumerator[T any, K comparable] struct {
src Enumerable[T]
ksel func(T) (K, error)
ks []K
m map[K][]T
i int
}
// GroupBy groups the elements of a sequence according to a specified key selector function.
func GroupBy[T any, K comparable, E IEnumerable[T]](src E, keySelector func(T) (K, error)) Enumerable[Grouping[T, K]] {
return func() Enumerator[Grouping[T, K]] {
return &groupByEnumerator[T, K]{
src: Enumerable[T](src),
ksel: keySelector,
}
}
}
func (e *groupByEnumerator[T, K]) Next() (def Grouping[T, K], _ error) {
if e.ks == nil {
ks := make([]K, 0)
m := make(map[K][]T)
err := ForEach(e.src, func(v T) error {
k, err := e.ksel(v)
if err != nil {
return err
}
if _, ok := m[k]; !ok {
ks = append(ks, k)
}
m[k] = append(m[k], v)
return nil
})
if err != nil {
return def, err
}
e.ks = ks
e.m = m
}
if e.i >= len(e.ks) {
return def, EOC
}
k := e.ks[e.i]
e.i++
return Grouping[T, K]{
Enumerable: FromSlice(e.m[k]),
Key: k,
}, nil
}