This repository has been archived by the owner on Aug 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmap.go
141 lines (118 loc) · 3.51 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package iter
import "github.com/barweiss/go-tuple"
// KVZipStrict returns an iterator that yields tuples of the input map's
// keys and values. While the value lookup occurs lazily, the keys must be
// accumulated immediately when the iterator is created, so this operation can
// be expensive for large maps. If this is a problem, see KVZipLazy.
func KVZipStrict[T comparable, U any](m map[T]U) Iter[tuple.T2[T, U]] {
var keys []T
for key := range m {
keys = append(keys, key)
}
return func() (tuple.T2[T, U], bool) {
if len(keys) > 0 {
next := keys[0]
keys = keys[1:]
return tuple.New2(next, m[next]), true
}
var z tuple.T2[T, U]
return z, false
}
}
// KVZipLazy returns an iterator that yields tuples of the input map's
// keys and values. This function uses a channel and a goroutine to manage key
// values lazily. Warning: if you don't consume the whole iterator, you will end
// up leaking a goroutine:
// https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html.
// Unless you're dealing with large maps where strict evaluation of keys may be
// problematic, KVZipStrict is recommended.
func KVZipLazy[T comparable, U any](m map[T]U) Iter[tuple.T2[T, U]] {
keyChan := make(chan tuple.T2[T, U])
go func() {
for key, value := range m {
keyChan <- tuple.New2(key, value)
}
close(keyChan)
}()
return func() (tuple.T2[T, U], bool) {
next, ok := <-keyChan
if ok {
return next, true
}
var z tuple.T2[T, U]
return z, false
}
}
// Map returns a new iterator that yields the results of applying the provided
// function to the input iterator.
func (i Iter[T]) Map(f func(T) T) Iter[T] {
return Map(i, f)
}
// Map returns a new iterator that yields the results of applying the provided
// function to the input iterator.
func Map[T, U any](i Iter[T], f func(T) U) Iter[U] {
return func() (U, bool) {
next, ok := i()
if ok {
return f(next), true
}
var z U
return z, false
}
}
// MapWhile returns a new iterator that yields the values produced by applying
// the provided function to the values of the input iterator, until the first
// error occurs. At that point, no further values are returned.
func (i Iter[T]) MapWhile(f func(T) (T, error)) Iter[T] {
return MapWhile(i, f)
}
// MapWhile returns a new iterator that yields the values produced by applying
// the provided function to the values of the input iterator, until the first
// error occurs. At that point, no further values are returned.
func MapWhile[T, U any](i Iter[T], f func(T) (U, error)) Iter[U] {
failed := false
return func() (U, bool) {
if failed {
var z U
return z, false
}
next, ok := i()
if ok {
if mappedNext, err := f(next); err == nil {
return mappedNext, true
}
failed = true
var z U
return z, false
}
var z U
return z, false
}
}
// FlatMap returns a new iterator that yields the values produced by iterators
// returned by the provided function when it is applied to values from the
// input iterator.
func (i Iter[T]) FlatMap(f func(T) Iter[T]) Iter[T] {
return FlatMap(i, f)
}
// FlatMap returns a new iterator that yields the values produced by iterators
// returned by the provided function when it is applied to values from the
// input iterator.
func FlatMap[T, U any](i Iter[T], f func(T) Iter[U]) Iter[U] {
curr := Empty[U]()
var self Iter[U]
self = func() (U, bool) {
next, ok := curr()
if ok {
return next, true
}
nextCurr, ok := i()
if ok {
curr = f(nextCurr)
return self()
}
var z U
return z, false
}
return self
}