Skip to content

Commit

Permalink
Merge pull request #2 from samber/feat-parallel
Browse files Browse the repository at this point in the history
Adding lop.Map and lop.ForEach
  • Loading branch information
samber committed Mar 3, 2022
2 parents 50e56b1 + 2566a93 commit def4dff
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.2.0 (2022-03-03)

Adding `lop.Map` and `lop.ForEach`.

## 1.1.0 (2022-03-03)

Adding `i int` param to `lo.Map()`, `lo.Filter()`, `lo.ForEach()` and `lo.Reduce()` predicates.
Expand Down
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ go1.18beta1:
go1.18beta1 download

build:
${BIN} build -v .
${BIN} build -v ./...

test:
go test -v .
watch-test: tools
reflex -R assets.go -t 50ms -s -- sh -c 'gotest -v .'
go test -v ./...
watch-test:
reflex -R assets.go -t 50ms -s -- sh -c 'gotest -v ./...'

bench:
gotest -benchmem -bench .
gotest -benchmem -bench ./...

coverage:
${BIN} test -v -coverprofile cover.out .
Expand Down
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ go get github.com/samber/lo
You can import `lo` using a basic statement:

```go
import "github.com/samber/lo"
import (
"github.com/samber/lo"
lop "github.com/samber/lo/parallel"
)
```

Then use one of the helpers below:
Expand Down Expand Up @@ -101,12 +104,25 @@ Constraints:
Manipulates a slice and transforms it to a slice of another type:

```go
import "github.com/samber/lo"

lo.Map[int64, string]([]int64{1, 2, 3, 4}, func(x int64, _ int) string {
return strconv.FormatInt(x, 10)
})
// []string{"1", "2", "3", "4"}
```

Parallel processing: like lo.Map(), but mapper is called in goroutine. Results are returns in the same order.

```go
import lop "github.com/samber/lo/parallel"

lop.Map[int64, string]([]int64{1, 2, 3, 4}, func(x int64, _ int) string {
return strconv.FormatInt(x, 10)
}, 2)
// []string{"1", "2", "3", "4"}
```

### Filter

Iterates over elements of collection, returning an array of all elements predicate returns truthy for.
Expand Down Expand Up @@ -146,7 +162,18 @@ Iterates over elements of collection and invokes iteratee for each element.
lo.ForEach[string]([]string{"hello", "world"}, func(x string, _ int) {
println(x)
})
// prints "hello\nworld"
// prints "hello\nworld\n"
```

Parallel processing: like lo.ForEach(), but callback is called in goroutine.

```go
import lop "github.com/samber/lo/parallel"

lop.ForEach[string]([]string{"hello", "world"}, func(x string, _ int) {
println(x)
})
// prints "hello\nworld\n" or "world\nhello\n"
```

### Uniq
Expand Down
7 changes: 2 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ go 1.18
require github.com/stretchr/testify v1.7.0

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
16 changes: 3 additions & 13 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
45 changes: 45 additions & 0 deletions parallel/slice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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()
}
24 changes: 24 additions & 0 deletions parallel/slice_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package parallel

import (
"testing"
"strconv"

"github.com/stretchr/testify/assert"
)

func TestMap(t *testing.T) {
is := assert.New(t)

result1 := Map[int, string]([]int{1, 2, 3, 4}, func(x int, _ int) string {
return "Hello"
})
result2 := Map[int64, string]([]int64{1, 2, 3, 4}, func(x int64, _ int) string {
return strconv.FormatInt(x, 10)
})

is.Equal(len(result1), 4)
is.Equal(len(result2), 4)
is.Equal(result1, []string{"Hello", "Hello", "Hello", "Hello"})
is.Equal(result2, []string{"1", "2", "3", "4"})
}

0 comments on commit def4dff

Please sign in to comment.