-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy patharrays.go
More file actions
339 lines (287 loc) · 8.43 KB
/
arrays.go
File metadata and controls
339 lines (287 loc) · 8.43 KB
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
package fusion
import (
"fmt"
"math/rand"
"time"
)
// Chunk splits a slice into chunks of a specified size
func Chunk[T any](arr []T, size int) [][]T {
length := len(arr)
if size <= 0 || length == 0 {
return nil
}
chunks := make([][]T, 0)
for i := 0; i < length; i += size {
end := i + size
if end > length {
end = length
}
chunks = append(chunks, arr[i:end])
}
return chunks
}
// Concat concatenates two or more slices into a single slice
func Concat[T any](arrays ...[]T) []T {
length := 0
for _, arr := range arrays {
length += len(arr)
}
concatenated := make([]T, 0, length)
for _, arr := range arrays {
concatenated = append(concatenated, arr...)
}
return concatenated
}
// Difference creates a slice of values that are not in the other given slices
func Difference[T comparable](arr []T, others ...[]T) []T {
diffSet := make(map[T]struct{})
for _, val := range arr {
diffSet[val] = struct{}{}
}
for _, other := range others {
for _, val := range other {
delete(diffSet, val)
}
}
difference := make([]T, 0, len(diffSet))
for val := range diffSet {
difference = append(difference, val)
}
return difference
}
// Every checks if all elements in the slice satisfy the given predicate.
// The predicate is invoked with three arguments: (value, index, array).
// It returns true if the predicate returns true for all elements, otherwise false.
func Every[T any](arr []T, predicate func(T, int, []T) bool) bool {
for i, value := range arr {
if !predicate(value, i, arr) {
return false
}
}
return true
}
// Fill modifies a slice by filling it with a specified value from a start index to an end index
func Fill(arr []interface{}, value interface{}, start int, end int) {
length := len(arr)
if start < 0 {
start = 0
}
if end > length {
end = length
}
for i := start; i < end; i++ {
arr[i] = value
}
}
// Filter filters the elements of a slice based on a predicate function.
// The predicate function is invoked with three arguments: (value, index, arg),
// and should return a boolean indicating whether the value should be included in the result.
func Filter[T any](arr []T, predicate func(int, T, interface{}) bool, arg interface{}) []T {
var result []T
for i, value := range arr {
if predicate(i, value, arg) {
result = append(result, value)
}
}
return result
}
// FindIndex returns the index of the first element in a slice that satisfies the provided testing function
func FindIndex(arr []interface{}, predicate func(interface{}) bool) int {
for i, val := range arr {
if predicate(val) {
return i
}
}
return -1
}
// Flatten flattens a slice of slices into a single slice
func Flatten(arr []interface{}) []interface{} {
flattened := make([]interface{}, 0)
for _, val := range arr {
switch v := val.(type) {
case []interface{}:
flattened = append(flattened, Flatten(v)...)
default:
flattened = append(flattened, v)
}
}
return flattened
}
// Includes checks if a given value is present in the slice.
// It returns true if the value is found, otherwise false.
func Includes[T comparable](arr []T, value T) bool {
for _, item := range arr {
if item == value {
return true
}
}
return false
}
// Intersection returns an array containing the unique values that are present in all of the input arrays.
func Intersection(arrays ...[]interface{}) []interface{} {
// Count occurrences of each element
counts := make(map[interface{}]int)
for _, arr := range arrays {
seen := make(map[interface{}]bool)
for _, elem := range arr {
if !seen[elem] {
counts[elem]++
seen[elem] = true
}
}
}
// Filter elements that appear in all arrays
var result []interface{}
for elem, count := range counts {
if count == len(arrays) {
result = append(result, elem)
}
}
return result
}
// Join concatenates all elements of an array into a single string using the provided separator.
func Join(arr []interface{}, separator string) string {
if len(arr) == 0 {
return ""
}
var result string
for i, elem := range arr {
if i > 0 {
result += separator
}
result += fmt.Sprintf("%v", elem)
}
return result
}
// Map applies a transformation function to each element of the input array/slice
// and returns a new array/slice with the transformed values.
func Map[T any, U any](arr []T, transformFunc func(int, T, interface{}) U, arg interface{}) []U {
result := make([]U, len(arr))
for i, element := range arr {
transformedValue := transformFunc(i, element, arg)
result[i] = transformedValue
}
return result
}
// Pull removes all occurrences of the specified values from a slice.
func Pull[T comparable](arr []T, values ...T) []T {
var result []T
excluded := make(map[T]struct{})
for _, value := range values {
excluded[value] = struct{}{}
}
for _, item := range arr {
if _, excluded := excluded[item]; !excluded {
result = append(result, item)
}
}
return result
}
// Reduce applies a function against an accumulator and each element in the slice (from left to right)
// to reduce it to a single value.
// The transform function is invoked with four arguments: (accumulator, value, index, arg).
// The initial value of the accumulator is provided as the initialValue parameter.
func Reduce[T any, R any](arr []T, transform func(R, T, int, interface{}) R, initialValue R, arg interface{}) R {
accumulator := initialValue
for i, value := range arr {
accumulator = transform(accumulator, value, i, arg)
}
return accumulator
}
// Remove removes all elements from the slice for which the predicate returns truthy,
// and returns an array of the removed elements.
// The predicate is invoked with three arguments: (value, index, array).
func Remove[T any](arr *[]T, predicate func(T, int, []T) bool) []T {
var removed []T
remaining := (*arr)[:0]
for index, value := range *arr {
if predicate(value, index, *arr) {
removed = append(removed, value)
} else {
remaining = append(remaining, value)
}
}
*arr = remaining
return removed
}
// Reverse reverses the elements of a slice in place
func Reverse[T any](arr []T) {
for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 {
arr[i], arr[j] = arr[j], arr[i]
}
}
// Shuffle shuffles the elements of the slice using the Fisher-Yates algorithm. It modifies the input slice in place.
func Shuffle[T any](arr []T) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := len(arr) - 1; i > 0; i-- {
j := r.Intn(i + 1)
arr[i], arr[j] = arr[j], arr[i]
}
}
// Slice returns a portion of a slice from a start index to an end index
func Slice[T any](arr []T, start, end int) []T {
if start < 0 {
start = 0
}
if end > len(arr) {
end = len(arr)
}
if start > end {
return nil
}
return arr[start:end]
}
// Some checks if at least one element in the slice satisfies the given predicate.
// The predicate is invoked with three arguments: (value, index, array).
// It returns true if the predicate returns true for any element, otherwise false.
func Some[T any](arr []T, predicate func(T, int, []T) bool) bool {
for i, value := range arr {
if predicate(value, i, arr) {
return true
}
}
return false
}
// Union returns a new slice that contains the unique elements from all input slices.
// The order of elements in the resulting slice is undefined.
func Union[T comparable](slices ...[]T) []T {
// Use a map to track unique elements
uniqueElements := make(map[T]struct{})
for _, slice := range slices {
for _, elem := range slice {
uniqueElements[elem] = struct{}{}
}
}
// Build the resulting slice from the unique elements
result := make([]T, 0, len(uniqueElements))
for elem := range uniqueElements {
result = append(result, elem)
}
return result
}
// Uniq creates a new slice of unique values in the order of their first occurrence in the original slice
func Uniq[T comparable](arr []T) []T {
seen := make(map[T]struct{})
var result []T
for _, value := range arr {
if _, exists := seen[value]; !exists {
seen[value] = struct{}{}
result = append(result, value)
}
}
return result
}
// Zip merges multiple slices into a single slice of tuples, where each tuple contains
// the corresponding elements from each of the input slices.
// The length of the resulting slice is determined by the shortest input slice.
func Zip[T1, T2 interface{}](slice1 []T1, slice2 []T2) [][]interface{} {
length := len(slice1)
if len(slice2) < length {
length = len(slice2)
}
zipped := make([][]interface{}, length)
for i := 0; i < length; i++ {
zipped[i] = []interface{}{slice1[i], slice2[i]}
}
return zipped
}