-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmap.go
249 lines (203 loc) · 5.36 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
package just
import "golang.org/x/exp/maps"
// MapMerge returns the map which contains all keys from m1, m2, and values
// from `fn(key, m1Value, m2Value)`.
func MapMerge[M ~map[K]V, K comparable, V any](m1, m2 M, fn func(k K, v1, v2 V) V) M {
m := make(M, len(m1))
for k, v := range m1 {
m[k] = fn(k, v, m2[k])
}
var emptyVal V
for k, v := range m2 {
if _, ok := m[k]; ok {
continue
}
m[k] = fn(k, emptyVal, v)
}
return m
}
// MapFilter returns the map which contains elements that
// `fn(key, value) == true`.
func MapFilter[M ~map[K]V, K comparable, V any](in M, fn func(k K, v V) bool) M {
m := make(M, len(in))
for k, v := range in {
if !fn(k, v) {
continue
}
m[k] = v
}
return m
}
// MapFilterKeys returns the map which contains elements that
// `fn(key) == true`. That is a simplified version of MapFilter.
func MapFilterKeys[M ~map[K]V, K comparable, V any](in M, fn func(k K) bool) M {
return MapFilter(in, func(k K, _ V) bool {
return fn(k)
})
}
// MapFilterValues returns the map which contains elements that
// `fn(value) == true`. That is a simplified version of MapFilter.
func MapFilterValues[M ~map[K]V, K comparable, V any](in M, fn func(v V) bool) M {
return MapFilter(in, func(_ K, v V) bool {
return fn(v)
})
}
// MapGetKeys returns all keys of the map.
func MapGetKeys[M ~map[K]V, K comparable, V any](m M) []K {
return maps.Keys(m)
}
// MapGetValues returns all values of the map. Not Uniq, unordered.
func MapGetValues[M ~map[K]V, K comparable, V any](m M) []V {
return maps.Values(m)
}
// KV represents the key-value of the map.
type KV[K comparable, V any] struct {
Key K
Val V
}
// MapPairs returns a slice of KV structs that contains key-value pairs.
func MapPairs[M ~map[K]V, K comparable, V any](m M) []KV[K, V] {
if len(m) == 0 {
return nil
}
res := make([]KV[K, V], len(m))
var i int
for k, v := range m {
res[i] = KV[K, V]{
Key: k,
Val: v,
}
i++
}
return res
}
// MapDefaults returns the map `m` after filling in its non-exists keys by
// `defaults`.
// Example: {1:1}, {1:0, 2:2} => {1:1, 2:2}
func MapDefaults[M ~map[K]V, K comparable, V any](m, defaults M) M {
res := MapCopy(m)
for k, v := range defaults {
if _, ok := res[k]; !ok {
res[k] = v
}
}
return res
}
// MapCopy returns a shallow copy of the map.
func MapCopy[M ~map[K]V, K comparable, V any](m M) M {
return maps.Clone(m)
}
// MapMap applies fn to all kv pairs from in.
func MapMap[M ~map[K]V, K, K1 comparable, V, V1 any](in M, fn func(K, V) (K1, V1)) map[K1]V1 {
res := make(map[K1]V1, len(in))
for k, v := range in {
k1, v1 := fn(k, v)
res[k1] = v1
}
return res
}
// MapMapErr applies fn to all kv pairs from in.
func MapMapErr[M ~map[K]V, K, K1 comparable, V, V1 any](in M, fn func(K, V) (K1, V1, error)) (map[K1]V1, error) {
res := make(map[K1]V1, len(in))
for k, v := range in {
k1, v1, err := fn(k, v)
if err != nil {
return nil, err
}
res[k1] = v1
}
return res, nil
}
// MapContainsKey returns true if key is exists in the map.
func MapContainsKey[M ~map[K]V, K comparable, V any](m M, key K) bool {
_, ok := m[key]
return ok
}
// MapContainsKeysAny returns true when at least one key exists in the map.
func MapContainsKeysAny[M ~map[K]V, K comparable, V any](m M, keys []K) bool {
if len(keys) == 0 {
return false
}
if len(m) == 0 {
return false
}
for i := range keys {
if MapContainsKey(m, keys[i]) {
return true
}
}
return false
}
// MapContainsKeysAll returns true when at all keys exist in the map.
func MapContainsKeysAll[M ~map[K]V, K comparable, V any](m M, keys []K) bool {
if len(keys) == 0 {
return false
}
if len(m) == 0 {
return false
}
for i := range keys {
if !MapContainsKey(m, keys[i]) {
return false
}
}
return true
}
// MapApply applies fn to each kv pair
func MapApply[M ~map[K]V, K comparable, V any](in M, fn func(k K, v V)) {
for k, v := range in {
fn(k, v)
}
}
// MapJoin will create a new map containing all key-value pairs from app input
// maps. If several maps have duplicate keys - the last write wins.
func MapJoin[M ~map[K]V, K comparable, V any](maps ...M) M {
res := make(M)
for i := range maps {
for k, v := range maps[i] {
res[k] = v
}
}
return res
}
// MapGetDefault returns a value for a given key or default value if the key
// is not present in the source map.
func MapGetDefault[M ~map[K]V, K comparable, V any](in M, key K, defaultVal V) V {
v, ok := in[key]
if !ok {
return defaultVal
}
return v
}
// MapNotNil returns the source map when it is not nil or creates an empty
// instance of this type.
func MapNotNil[T ~map[K]V, K comparable, V any](in T) T {
if in == nil {
return make(T, 0)
}
return in
}
// MapDropKeys remove all keys from the source map. Map will change in place.
func MapDropKeys[M ~map[K]V, K comparable, V any](in M, keys ...K) {
if len(keys) == 0 || len(in) == 0 {
return
}
for i := range keys {
delete(in, keys[i])
}
}
// MapPopKeyDefault will return value for given key and delete this key from source map.
// In case of key do not presented in map - returns default value.
func MapPopKeyDefault[M ~map[K]V, K comparable, V any](in M, key K, def V) V {
val, ok := in[key]
if ok {
delete(in, key)
return val
}
return def
}
// MapSetVal update key with value for given map and return updated map.
func MapSetVal[M ~map[K]V, K comparable, V any](in M, key K, val V) M {
in[key] = val
return in
}