-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaps.go
225 lines (192 loc) · 5.51 KB
/
maps.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
package core
import (
"container/list"
)
// Keys returns the list of keys of a map
func Keys[K comparable, T any](m map[K]T) []K {
out := make([]K, 0, len(m))
for k := range m {
out = append(out, k)
}
return out
}
// SortedKeys returns a sorted list of the keys of a map
func SortedKeys[K Ordered, T any](m map[K]T) []K {
keys := Keys(m)
SliceSort(keys, func(a, b K) int {
switch {
case a == b:
return 0
case a < b:
return -1
default:
return 1
}
})
return keys
}
// MapValue returns a value of an entry or a default if
// not found
func MapValue[K comparable, V any](m map[K]V, key K, def V) (V, bool) {
if val, ok := m[key]; ok {
return val, true
}
return def, false
}
// MapContains tells if a given map contains a key.
// this helper is intended for switch/case conditions
func MapContains[K comparable](m map[K]any, key K) bool {
_, ok := m[key]
return ok
}
// MapListContains checks if the list.List on a map contains an element
func MapListContains[K comparable, T comparable](m map[K]*list.List, key K, v T) bool {
return MapListContainsFn(m, key, v, func(va, vb T) bool {
return va == vb
})
}
// MapListContainsFn checks if the list.List on a map contains an element using a match functions
func MapListContainsFn[K comparable, T any](m map[K]*list.List, key K, v T,
eq func(T, T) bool) bool {
//
if m != nil && eq == nil {
if l, ok := m[key]; ok {
return ListContainsFn(l, v, eq)
}
}
return false
}
// MapListForEach calls a function for each value on a map entry until told to stop
func MapListForEach[K comparable, T any](m map[K]*list.List, key K,
fn func(v T) bool) {
//
if m == nil || fn == nil {
return
}
if l, ok := m[key]; ok {
ListForEach(l, fn)
}
}
// MapListForEachElement calls a function for each element on a map entry until told to stop
func MapListForEachElement[K comparable](m map[K]*list.List, key K,
fn func(el *list.Element) bool) {
//
if m == nil || fn == nil {
return
}
if l, ok := m[key]; ok {
ListForEachElement(l, fn)
}
}
// MapListInsert adds a value at the front of the list of a map entry
func MapListInsert[K comparable, T any](m map[K]*list.List, key K, v T) {
getMapList(m, key).PushFront(v)
}
func getMapList[K comparable](m map[K]*list.List, key K) *list.List {
var l *list.List
var ok bool
if l, ok = m[key]; !ok {
l = list.New()
m[key] = l
}
return l
}
// MapListInsertUnique adds a value at the front of the list of a map entry
// if it's not already there
func MapListInsertUnique[K comparable, T comparable](m map[K]*list.List, key K, v T) {
MapListInsertUniqueFn(m, key, v, func(va, vb T) bool {
return va == vb
})
}
// MapListInsertUniqueFn adds a value at the front of the list of a map entry
// if it's not already there using a function to compare values
func MapListInsertUniqueFn[K comparable, T any](m map[K]*list.List, key K, v T,
eq func(va, vb T) bool) {
if m == nil || eq == nil {
return
}
l := getMapList(m, key)
if !ListContainsFn(l, v, eq) {
l.PushFront(v)
}
}
// MapListAppend adds a value at the end of the list of a map entry
func MapListAppend[K comparable, T any](m map[K]*list.List, key K, v T) {
getMapList(m, key).PushBack(v)
}
// MapListAppendUnique adds a value at the end of the list of a map entry
// if it's not already there
func MapListAppendUnique[K comparable, T comparable](m map[K]*list.List, key K, v T) {
MapListAppendUniqueFn(m, key, v, func(va, vb T) bool {
return va == vb
})
}
// MapListAppendUniqueFn adds a value at the end of the list of a map entry
// if it's not already there using a function to compare values
func MapListAppendUniqueFn[K comparable, T any](m map[K]*list.List, key K, v T,
eq func(T, T) bool) {
if m != nil && eq != nil {
l := getMapList(m, key)
if !ListContainsFn(l, v, eq) {
l.PushBack(v)
}
}
}
// MapListCopy duplicates a map containing a list.List
func MapListCopy[T comparable](src map[T]*list.List) map[T]*list.List {
fn := func(v any) (any, bool) { return v, true }
return MapListCopyFn(src, fn)
}
// MapListCopyFn duplicates a map containing a list.List but
// allows the element's values to be cloned by a helper function
func MapListCopyFn[K comparable, V any](src map[K]*list.List,
fn func(v V) (V, bool)) map[K]*list.List {
out := make(map[K]*list.List, len(src))
for k, l := range src {
out[k] = ListCopyFn(l, fn)
}
return out
}
// MapAllListContains check if a value exists on any entry of the map
func MapAllListContains[K comparable, T comparable](m map[K]*list.List, v T) bool {
if m != nil {
return MapAllListContainsFn(m, func(v1 T) bool {
return v == v1
})
}
return false
}
// MapAllListContainsFn check if a value exists on any entry of the map using a match function
func MapAllListContainsFn[K comparable, T any](m map[K]*list.List, match func(v T) bool) bool {
var found bool
fn := func(v1 T) bool {
found = match(v1)
return found
}
if m != nil && match != nil {
for _, l := range m {
ListForEach(l, fn)
if found {
return true
}
}
}
return false
}
// MapAllListForEach calls a function for each value on all map entries until told to stop
func MapAllListForEach[K comparable, T any](m map[K]*list.List, fn func(v T) bool) {
MapAllListContainsFn(m, fn)
}
// MapAllListForEachElement calls a function for each element on all map entries until told to stop
func MapAllListForEachElement[K comparable](m map[K]*list.List, fn func(*list.Element) bool) {
var term bool
for _, l := range m {
ListForEachElement(l, func(el *list.Element) bool {
term = fn(el)
return term
})
if term {
break
}
}
}