forked from samber/lo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslice.go
130 lines (95 loc) · 2.73 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
package parallel
import "sync"
// Map manipulates a slice and transforms it to a slice of another type.
// `iteratee` is call in parallel. Result keep the same order.
func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {
result := make([]R, len(collection))
var wg sync.WaitGroup
wg.Add(len(collection))
for i, item := range collection {
go func(_item T, _i int) {
res := iteratee(_item, _i)
result[_i] = res
wg.Done()
}(item, i)
}
wg.Wait()
return result
}
// ForEach iterates over elements of collection and invokes iteratee for each element.
// `iteratee` is call in parallel.
func ForEach[T any](collection []T, iteratee func(item T, index int)) {
var wg sync.WaitGroup
wg.Add(len(collection))
for i, item := range collection {
go func(_item T, _i int) {
iteratee(_item, _i)
wg.Done()
}(item, i)
}
wg.Wait()
}
// Times invokes the iteratee n times, returning an array of the results of each invocation.
// The iteratee is invoked with index as argument.
// `iteratee` is call in parallel.
func Times[T any](count int, iteratee func(index int) T) []T {
result := make([]T, count)
var wg sync.WaitGroup
wg.Add(count)
for i := 0; i < count; i++ {
go func(_i int) {
item := iteratee(_i)
result[_i] = item
wg.Done()
}(i)
}
wg.Wait()
return result
}
// GroupBy returns an object composed of keys generated from the results of running each element of collection through iteratee.
// `iteratee` is call in parallel.
func GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) map[U]Slice {
result := map[U]Slice{}
var mu sync.Mutex
var wg sync.WaitGroup
wg.Add(len(collection))
for _, item := range collection {
go func(_item T) {
key := iteratee(_item)
mu.Lock()
result[key] = append(result[key], _item)
mu.Unlock()
wg.Done()
}(item)
}
wg.Wait()
return result
}
// PartitionBy returns an array of elements split into groups. The order of grouped values is
// determined by the order they occur in collection. The grouping is generated from the results
// of running each element of collection through iteratee.
// `iteratee` is call in parallel.
func PartitionBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K) []Slice {
result := []Slice{}
seen := map[K]int{}
var mu sync.Mutex
var wg sync.WaitGroup
wg.Add(len(collection))
for _, item := range collection {
go func(_item T) {
key := iteratee(_item)
mu.Lock()
resultIndex, ok := seen[key]
if !ok {
resultIndex = len(result)
seen[key] = resultIndex
result = append(result, []T{})
}
result[resultIndex] = append(result[resultIndex], _item)
mu.Unlock()
wg.Done()
}(item)
}
wg.Wait()
return result
}