-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
slice.go
207 lines (162 loc) · 4.42 KB
/
slice.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
package fn
import "golang.org/x/exp/constraints"
// Number is a type constraint for all numeric types in Go (integers,
// float and complex numbers)
type Number interface {
constraints.Integer | constraints.Float | constraints.Complex
}
// All returns true when the supplied predicate evaluates to true for all of
// the values in the slice.
func All[A any](pred func(A) bool, s []A) bool {
for _, val := range s {
if !pred(val) {
return false
}
}
return true
}
// Any returns true when the supplied predicate evaluates to true for any of
// the values in the slice.
func Any[A any](pred func(A) bool, s []A) bool {
for _, val := range s {
if pred(val) {
return true
}
}
return false
}
// Map applies the function argument to all members of the slice and returns a
// slice of those return values.
func Map[A, B any](f func(A) B, s []A) []B {
res := make([]B, 0, len(s))
for _, val := range s {
res = append(res, f(val))
}
return res
}
// Filter creates a new slice of values where all the members of the returned
// slice pass the predicate that is supplied in the argument.
func Filter[A any](pred func(A) bool, s []A) []A {
res := make([]A, 0)
for _, val := range s {
if pred(val) {
res = append(res, val)
}
}
return res
}
// Foldl iterates through all members of the slice left to right and reduces
// them pairwise with an accumulator value that is seeded with the seed value in
// the argument.
func Foldl[A, B any](f func(B, A) B, seed B, s []A) B {
acc := seed
for _, val := range s {
acc = f(acc, val)
}
return acc
}
// Foldr, is exactly like Foldl except that it iterates over the slice from
// right to left.
func Foldr[A, B any](f func(A, B) B, seed B, s []A) B {
acc := seed
for i := range s {
acc = f(s[len(s)-1-i], acc)
}
return acc
}
// Find returns the first value that passes the supplied predicate, or None if
// the value wasn't found.
func Find[A any](pred func(A) bool, s []A) Option[A] {
for _, val := range s {
if pred(val) {
return Some(val)
}
}
return None[A]()
}
// Flatten takes a slice of slices and returns a concatenation of those slices.
func Flatten[A any](s [][]A) []A {
sz := Foldr(
func(l []A, acc uint64) uint64 {
return uint64(len(l)) + acc
}, 0, s,
)
res := make([]A, 0, sz)
for _, val := range s {
res = append(res, val...)
}
return res
}
// Replicate generates a slice of values initialized by the prototype value.
func Replicate[A any](n uint, val A) []A {
res := make([]A, n)
for i := range res {
res[i] = val
}
return res
}
// Span, applied to a predicate and a slice, returns two slices where the first
// element is the longest prefix (possibly empty) of slice elements that
// satisfy the predicate and second element is the remainder of the slice.
func Span[A any](pred func(A) bool, s []A) ([]A, []A) {
for i := range s {
if !pred(s[i]) {
fst := make([]A, i)
snd := make([]A, len(s)-i)
copy(fst, s[:i])
copy(snd, s[i:])
return fst, snd
}
}
res := make([]A, len(s))
copy(res, s)
return res, []A{}
}
// SplitAt(n, s) returns a tuple where first element is s prefix of length n
// and second element is the remainder of the list.
func SplitAt[A any](n uint, s []A) ([]A, []A) {
fst := make([]A, n)
snd := make([]A, len(s)-int(n))
copy(fst, s[:n])
copy(snd, s[n:])
return fst, snd
}
// ZipWith combines slice elements with the same index using the function
// argument, returning a slice of the results.
func ZipWith[A, B, C any](f func(A, B) C, a []A, b []B) []C {
var l uint
if la, lb := len(a), len(b); la < lb {
l = uint(la)
} else {
l = uint(lb)
}
res := make([]C, l)
for i := 0; i < int(l); i++ {
res[i] = f(a[i], b[i])
}
return res
}
// SliceToMap converts a slice to a map using the provided key and value
// functions.
func SliceToMap[A any, K comparable, V any](s []A, keyFunc func(A) K,
valueFunc func(A) V) map[K]V {
res := make(map[K]V, len(s))
for _, val := range s {
key := keyFunc(val)
value := valueFunc(val)
res[key] = value
}
return res
}
// Sum calculates the sum of a slice of numbers, `items`.
func Sum[B Number](items []B) B {
return Foldl(func(a, b B) B {
return a + b
}, 0, items)
}
// HasDuplicates checks if the given slice contains any duplicate elements.
// It returns false if there are no duplicates in the slice (i.e., all elements
// are unique), otherwise returns false.
func HasDuplicates[A comparable](items []A) bool {
return len(NewSet(items...)) != len(items)
}