-
Notifications
You must be signed in to change notification settings - Fork 6
/
tomap.go
58 lines (54 loc) · 1.91 KB
/
tomap.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
package go2linq
import (
"iter"
"github.com/solsw/errorhelper"
)
// [ToMap] creates a [map] from a sequence according to a specified key selector function.
//
// [map]: https://go.dev/ref/spec#Map_types
// [ToMap]: https://learn.microsoft.com/dotnet/api/system.linq.enumerable.todictionary
func ToMap[Source any, Key comparable](source iter.Seq[Source], keySelector func(Source) Key) (map[Key]Source, error) {
if source == nil {
return nil, errorhelper.CallerError(ErrNilSource)
}
if keySelector == nil {
return nil, errorhelper.CallerError(ErrNilSelector)
}
m := make(map[Key]Source)
for s := range source {
k := keySelector(s)
if _, ok := m[k]; ok {
return nil, errorhelper.CallerError(ErrDuplicateKeys)
}
m[k] = s
}
return m, nil
}
// [ToMapSel] creates a [map] from a sequence according to specified key selector and element selector functions.
//
// Since Go's map does not support custom equaler to determine equality of the keys,
// LINQ's key comparer is not implemented.
// Similar to the keys equality functionality may be achieved using appropriate key selector.
// Example of custom key selector that mimics case-insensitive equaler for string keys
// is presented in [TestCustomSelector_string_string_int].
//
// [map]: https://go.dev/ref/spec#Map_types
// [ToMapSel]: https://learn.microsoft.com/dotnet/api/system.linq.enumerable.todictionary
func ToMapSel[Source any, Key comparable, Element any](source iter.Seq[Source],
keySelector func(Source) Key, elementSelector func(Source) Element) (map[Key]Element, error) {
if source == nil {
return nil, errorhelper.CallerError(ErrNilSource)
}
if keySelector == nil || elementSelector == nil {
return nil, errorhelper.CallerError(ErrNilSelector)
}
m := make(map[Key]Element)
for s := range source {
k := keySelector(s)
if _, ok := m[k]; ok {
return nil, errorhelper.CallerError(ErrDuplicateKeys)
}
m[k] = elementSelector(s)
}
return m, nil
}