-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmap.go
70 lines (63 loc) · 2.06 KB
/
map.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
package iter
import (
"context"
"github.com/patrickhuber/go-types"
"github.com/patrickhuber/go-types/option"
"github.com/patrickhuber/go-types/tuple"
)
// FromMapAsync returns a call to FromChannel with a channel created by iterating over the map in a go routine
// The context passed in is used to pass the WithContext chanel option to the FromChannel call
func FromMapAsync[TKey comparable, TValue any](m map[TKey]TValue, cx context.Context) Iterator[types.Tuple2[TKey, TValue]] {
ch := make(chan types.Tuple2[TKey, TValue])
go func(ch chan types.Tuple2[TKey, TValue], cx context.Context) {
defer close(ch)
for k, v := range m {
select {
case ch <- tuple.New2(k, v):
case <-cx.Done():
return
}
}
}(ch, cx)
return FromChannel(ch, WithContext[types.Tuple2[TKey, TValue]](cx))
}
// FromMap returns an iterator over the given map.
// FromMap captures keys of the map in the first call to `Next()`.
// Subsequent calls to `Next()` track an index into the key slice to return the next key value pair.
// Each call to `Next()` returns an Option tuple of Key Value pairs.
func FromMap[TKey comparable, TValue any](m map[TKey]TValue) Iterator[types.Tuple2[TKey, TValue]] {
return &mapIterator[TKey, TValue]{
m: m,
}
}
// mapIterator holds the list of keys and uses it to index into the hashmap
// I looked at using go routines but managing timeouts and etc made it more difficult
type mapIterator[TKey comparable, TValue any] struct {
keys Iterator[TKey]
m map[TKey]TValue
}
func (mi *mapIterator[TKey, TValue]) Next() types.Option[types.Tuple2[TKey, TValue]] {
// first iteration, provide the list of keys
if mi.keys == nil {
// size to the map but set len to zero
keys := make([]TKey, 0, len(mi.m))
for k := range mi.m {
keys = append(keys, k)
}
mi.keys = FromSlice(keys)
}
none := option.None[types.Tuple2[TKey, TValue]]()
for {
switch next := mi.keys.Next().(type) {
case types.Some[TKey]:
k := next.Value
v, ok := mi.m[k]
if !ok {
continue
}
return option.Some(tuple.New2(k, v))
case types.None[TKey]:
return none
}
}
}