Skip to content

Upgrade superlo #1

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 5 commits into from
Nov 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -2,6 +2,4 @@ module github.com/go-utils/superlo

go 1.20

require github.com/samber/lo v1.38.1

require golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
require golang.org/x/sync v0.5.0
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
60 changes: 49 additions & 11 deletions map.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,56 @@
package superlo

import "github.com/samber/lo"
import (
"sync"

"golang.org/x/sync/errgroup"
)

// Map - returns a new collection of mapped values and error
func Map[T any, R any](collection []T, iteratee func(item T, index int) (R, error)) (mappedCollection []R, topErr error) {
defer func() {
_ = recover()
}()
return lo.Map(collection, func(item T, index int) R {
returnValue, err := iteratee(item, index)
func Map[T any, R any](collection []T, iteratee func(item T, index int) (R, error)) ([]R, error) {
result := make([]R, len(collection))

for i, item := range collection {
returnValue, err := iteratee(item, i)
if err != nil {
topErr = err
panic(nil)
return nil, err
}
return returnValue
}), nil
result[i] = returnValue
}

return result, nil
}

// ParallelMap - returns a new collection of mapped values and error
// `iteratee` is call in parallel. Result keep the same order.
func ParallelMap[T any, R any](collection []T, iteratee func(item T, index int) (R, error)) ([]R, error) {
result := make([]R, len(collection))

var (
eg errgroup.Group
mu sync.Mutex
)

for i, item := range collection {
func(_item T, _i int) {
eg.Go(func() error {
returnValue, err := iteratee(_item, _i)
if err != nil {
return err
}

mu.Lock()
result[_i] = returnValue
mu.Unlock()

return nil
})
}(item, i)
}

if err := eg.Wait(); err != nil {
return nil, err
}

return result, nil
}
50 changes: 50 additions & 0 deletions map_test.go
Original file line number Diff line number Diff line change
@@ -57,3 +57,53 @@ func TestMap(t *testing.T) {
})
}
}

func TestParallelMap(t *testing.T) {
type args[T any, R any] struct {
collection []T
iteratee func(item T, index int) (R, error)
}
type testCase[T any, R any] struct {
name string
args args[T, R]
wantMappedCollection []R
wantErr bool
}
tests := []testCase[int, int]{
{
name: "OK",
args: args[int, int]{
collection: []int{1, 2, 3, 4, 5},
iteratee: func(item int, index int) (int, error) {
return item * index, nil
},
},
wantMappedCollection: []int{0, 2, 6, 12, 20},
},
{
name: "NG",
args: args[int, int]{
collection: []int{0, 2, 3, 4, 6},
iteratee: func(item int, index int) (int, error) {
if item%2 != 0 {
return 0, errors.New("error")
}
return item * index, nil
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotMappedCollection, err := superlo.ParallelMap(tt.args.collection, tt.args.iteratee)
if (err != nil) != tt.wantErr {
t.Errorf("ParallelMap() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotMappedCollection, tt.wantMappedCollection) {
t.Errorf("ParallelMap() gotMappedCollection = %v, want %v", gotMappedCollection, tt.wantMappedCollection)
}
})
}
}