-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharray.go
298 lines (253 loc) · 6.23 KB
/
array.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
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
package filter
import (
"crypto/rand"
"errors"
"fmt"
"math/big"
"reflect"
"strings"
)
var (
ErrNotSlice = errors.New("expected input to be a slice")
ErrEmptySlice = errors.New("slice is empty")
ErrInvalidArguments = errors.New("invalid number of arguments")
)
// Unique removes duplicate elements from a slice.
func Unique(input interface{}) ([]interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
var uniqueItems []interface{}
for _, item := range slice {
if !contains(uniqueItems, item) {
uniqueItems = append(uniqueItems, item)
}
}
return uniqueItems, nil
}
// Join joins the elements of a slice into a single string with a given separator.
func Join(input interface{}, separator string) (string, error) {
if separator == "" {
return "", ErrInvalidArguments
}
slice, err := toSlice(input)
if err != nil {
return "", err
}
strs := make([]string, 0, len(slice))
for _, item := range slice {
strs = append(strs, fmt.Sprint(item))
}
return strings.Join(strs, separator), nil
}
// First returns the first element of a slice.
func First(input interface{}) (interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
if len(slice) > 0 {
return slice[0], nil
}
return nil, ErrEmptySlice
}
// Index returns the element at a specified index in a slice.
func Index(input interface{}, index int) (interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
if index < 0 || index >= len(slice) {
return nil, ErrIndexOutOfRange
}
return slice[index], nil
}
// Last returns the last element of a slice.
func Last(input interface{}) (interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
if len(slice) == 0 {
return nil, ErrEmptySlice
}
return slice[len(slice)-1], nil
}
// Random selects a random element from a slice.
func Random(input interface{}) (interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
if len(slice) == 0 {
return nil, ErrEmptySlice
}
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(slice))))
if err != nil {
return nil, err
}
randomIndex := n.Int64()
return slice[randomIndex], nil
}
// Reverse reverses the order of elements in a slice.
func Reverse(input interface{}) ([]interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
result := make([]interface{}, len(slice))
if len(slice) == 0 {
return result, nil
}
copy(result, slice)
for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
result[i], result[j] = result[j], result[i]
}
return result, nil
}
// Shuffle randomly rearranges the elements of the slice.
func Shuffle(input interface{}) ([]interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
// Using crypto/rand to securely shuffle the slice.
n := len(slice)
for i := n - 1; i > 0; i-- {
// Generate a random index from 0 to i.
num, err := rand.Int(rand.Reader, big.NewInt(int64(i+1)))
if err != nil {
return nil, err // handle the error from rand.Int
}
j := num.Int64() // convert *big.Int to int64, then to int
// Swap the elements at indices i and j.
slice[i], slice[j] = slice[j], slice[i]
}
return slice, nil
}
// Size returns the size (length) of a slice.
func Size(input interface{}) (int, error) {
slice, err := toSlice(input)
if err != nil {
return 0, err
}
return len(slice), nil
}
// Max returns the maximum value from a slice of float64.
func Max(input interface{}) (float64, error) {
slice, err := toFloat64Slice(input)
if err != nil {
return 0, err
}
if len(slice) == 0 {
return 0, ErrEmptySlice
}
maxVal := slice[0]
for _, val := range slice[1:] {
if val > maxVal {
maxVal = val
}
}
return maxVal, nil
}
// Min returns the minimum value from a slice of float64.
func Min(input interface{}) (float64, error) {
slice, err := toFloat64Slice(input)
if err != nil {
return 0, err
}
if len(slice) == 0 {
return 0, ErrEmptySlice
}
minVal := slice[0]
for _, val := range slice[1:] {
if val < minVal {
minVal = val
}
}
return minVal, nil
}
// Sum calculates the sum of all elements in a slice of float64.
func Sum(input interface{}) (float64, error) {
slice, err := toFloat64Slice(input)
if err != nil {
return 0, err
}
var sum float64
for _, val := range slice {
sum += val
}
return sum, nil
}
// Average calculates the average value of elements in a slice of float64.
func Average(input interface{}) (float64, error) {
slice, err := toFloat64Slice(input)
if err != nil {
return 0, err
}
if len(slice) == 0 {
return 0, ErrEmptySlice
}
sum := 0.0
for _, val := range slice {
sum += val
}
average := sum / float64(len(slice))
return average, nil
}
// Map returns a slice of values for a specified key from each map in the input slice.
// If the key does not exist in an item, the corresponding value in the result slice will be nil.
func Map(input interface{}, key string) ([]interface{}, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
result := make([]interface{}, 0, len(slice))
for _, item := range slice {
value, err := Extract(item, key)
if err != nil {
result = append(result, nil)
continue
}
result = append(result, value)
}
return result, nil
}
// contains checks if a slice contains a specific element.
func contains(slice []interface{}, item interface{}) bool {
for _, elem := range slice {
if elem == item {
return true
}
}
return false
}
// toFloat64Slice attempts to convert an interface{} to a slice of float64.
func toFloat64Slice(input interface{}) ([]float64, error) {
slice, err := toSlice(input)
if err != nil {
return nil, err
}
result := make([]float64, 0, len(slice))
for _, item := range slice {
val, err := toFloat64(item)
if err != nil {
return nil, err
}
result = append(result, val)
}
return result, nil
}
// toSlice attempts to convert an interface{} to a slice of interface{}.
func toSlice(input interface{}) ([]interface{}, error) {
valRef := reflect.ValueOf(input)
if valRef.Kind() != reflect.Slice {
return nil, ErrNotSlice
}
var result []interface{}
for i := 0; i < valRef.Len(); i++ {
result = append(result, valRef.Index(i).Interface())
}
return result, nil
}