-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathslice.go
140 lines (118 loc) · 3.62 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
package slices
import "iter"
// Filter returns a new slice consisting of all elements that pass the predicate function
func Filter[TSlice ~[]T, T any](slice TSlice, predicate func(T) bool) iter.Seq[T] {
return func(yield func(T) bool) {
for _, t := range slice {
if predicate(t) {
if !yield(t) {
return
}
}
}
}
}
// FirstMatch returns the first element that passes the predicate function.
// If no element is found the zero value of the type will be returned.
func FirstMatch[TSlice ~[]T, T any](slice TSlice, predicate func(T) bool) T {
for _, t := range slice {
if predicate(t) {
return t
}
}
var zero T
return zero
}
// LastMatch returns the last element that passes the predicate function.
// If no element is found the zero value of the type will be returned.
func LastMatch[TSlice ~[]T, T any](slice TSlice, predicate func(T) bool) T {
for i := len(slice) - 1; i >= 0; i-- {
if predicate(slice[i]) {
return slice[i]
}
}
var zero T
return zero
}
// AnyMatch returns true if any element passes the predicate function
func AnyMatch[TSlice ~[]T, T any](slice TSlice, predicate func(T) bool) bool {
for _, t := range slice {
if predicate(t) {
return true
}
}
return false
}
// AllMatch returns true if all elements pass the predicate function
func AllMatch[TSlice ~[]T, T any](slice TSlice, predicate func(T) bool) bool {
for _, t := range slice {
if !predicate(t) {
return false
}
}
return true
}
// Map returns a new slice where each element is the result of fn for the corresponding element in the original slice
func Map[TSlice ~[]T, T any, U any](slice []T, fn func(T) U) []U {
result := make([]U, len(slice))
for i, t := range slice {
result[i] = fn(t)
}
return result
}
// Contains returns true if find appears in slice
func Contains[TSlice ~[]T, T comparable](slice TSlice, find T) bool {
for _, t := range slice {
if t == find {
return true
}
}
return false
}
// IndexOf returns the index of find if it appears in slice. If find is not in slice, -1 will be returned.
func IndexOf[TSlice ~[]T, T comparable](slice TSlice, find T) int {
for i, t := range slice {
if t == find {
return i
}
}
return -1
}
// GroupBy returns a map that is keyed by keySelector and contains a slice of elements returned by valSelector
func GroupBy[TSlice ~[]T, T any, K comparable, V any](slice TSlice, keySelector func(T) K, valSelector func(T) V) map[K][]V {
grouping := make(map[K][]V)
for _, t := range slice {
key := keySelector(t)
grouping[key] = append(grouping[key], valSelector(t))
}
return grouping
}
// ToSet returns a map keyed by keySelector and contains a value of an empty struct
func ToSet[TSlice ~[]T, T any, K comparable](slice TSlice, keySelector func(T) K) iter.Seq2[K, struct{}] {
return func(yield func(K, struct{}) bool) {
for _, t := range slice {
if !yield(keySelector(t), struct{}{}) {
return
}
}
}
}
// ToMap return a map that is keyed keySelector and has the value of valSelector for each element in slice.
// If multiple elements return the same key the element that appears later in slice will be chosen.
func ToMap[TSlice ~[]T, T any, K comparable, V any](slice TSlice, keySelector func(T) K, valSelector func(T) V) iter.Seq2[K, V] {
return func(yield func(K, V) bool) {
for _, t := range slice {
if !yield(keySelector(t), valSelector(t)) {
return
}
}
}
}
// YieldAll iterates over all elements from a provided iterator and returns a slice containing all elements from the iterator.
func YieldAll[TSlice ~[]T, T any](i iter.Seq[T]) TSlice {
result := make(TSlice, 0)
for v := range i {
result = append(result, v)
}
return result
}