Files
lo/parallel/slice.go

113 lines
2.3 KiB
Go

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(T, int) R) []R {
result := make([]R, len(collection))
var mu sync.Mutex
var wg sync.WaitGroup
wg.Add(len(collection))
for i, item := range collection {
go func (_item T, _i int) {
res := iteratee(_item, _i)
mu.Lock()
result[_i] = res
mu.Unlock()
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(T, 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()
}
// 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](collection []T, iteratee func(T) U) map[U][]T {
result := map[U][]T{}
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()
if _, ok := result[key]; !ok {
result[key] = []T{}
}
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](collection []T, iteratee func (x T) K) [][]T {
result := [][]T{}
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()
}(item)
}
wg.Wait()
return result
}