Skip to content

Commit

Permalink
feat: add Product and ProductBy functions
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] authored and JohnDevitt committed Dec 3, 2024
1 parent efef0ff commit 9587591
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 4 deletions.
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ Supported math helpers:
- [Clamp](#clamp)
- [Sum](#sum)
- [SumBy](#sumby)
- [Product](#product)
- [ProductBy](#productby)
- [Mean](#mean)
- [MeanBy](#meanby)

Expand Down Expand Up @@ -787,7 +789,6 @@ l := lo.DropByIndex([]int{0, 1, 2, 3, 4, 5}, 2, 4, -1)

[[play](https://go.dev/play/p/JswS7vXRJP2)]


### Reject

The opposite of Filter, this method returns the elements of collection that predicate does not return truthy for.
Expand All @@ -806,6 +807,7 @@ odd := lo.Reject([]int{1, 2, 3, 4}, func(x int, _ int) bool {
The opposite of FilterMap, this method returns a slice which obtained after both filtering and mapping using the given callback function.

The callback function should return two values:

- the result of the mapping operation and
- whether the result element should be included or not.

Expand Down Expand Up @@ -1062,7 +1064,7 @@ keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 3})

### UniqKeys

Creates an array of unique map keys.
Creates an array of unique map keys.

```go
keys := lo.UniqKeys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
Expand Down Expand Up @@ -1411,7 +1413,35 @@ sum := lo.SumBy(strings, func(item string) int {
// 6
```

[[play](https://go.dev/play/p/Dz_a_7jN_ca)]
### Product

Calculates the product of the values in a collection.

If collection is empty 0 is returned.

```go
list := []int{1, 2, 3, 4, 5}
sum := lo.Product(list)
// 120
```

[[play](https://go.dev/play/p/2_kjM_smtAH)]

### ProductBy

Calculates the product of the values in a collection using the given return value from the iteration function.

If collection is empty 0 is returned.

```go
strings := []string{"foo", "bar"}
sum := lo.ProductBy(strings, func(item string) int {
return len(item)
})
// 9
```

[[play](https://go.dev/play/p/wadzrWr9Aer)]

### Mean

Expand Down Expand Up @@ -2421,6 +2451,7 @@ first := lo.FirstOrEmpty([]int{1, 2, 3})
first := lo.FirstOrEmpty([]int{})
// 0
```

### FirstOr

Returns the first element of a collection or the fallback value if empty.
Expand Down Expand Up @@ -2458,6 +2489,7 @@ last := lo.LastOrEmpty([]int{1, 2, 3})
last := lo.LastOrEmpty([]int{})
// 0
```

### LastOr

Returns the first element of a collection or the fallback value if empty.
Expand Down Expand Up @@ -3213,7 +3245,6 @@ iterations, duration, ok := lo.WaitFor(laterTrue, 10*time.Millisecond, 5*time.Mi
// false
```


### WaitForWithContext

Runs periodically until a condition is validated or context is invalid.
Expand Down
38 changes: 38 additions & 0 deletions math.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,44 @@ func SumBy[T any, R constraints.Float | constraints.Integer | constraints.Comple
return sum
}

// Product gets the product of the values in a collection. If collection is empty 0 is returned.
// Play: https://go.dev/play/p/2_kjM_smtAH
func Product[T constraints.Float | constraints.Integer | constraints.Complex](collection []T) T {

if collection == nil {
return 0
}

if len(collection) == 0 {
return 0
}

var product T = 1
for i := range collection {
product *= collection[i]
}
return product
}

// ProductBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 0 is returned.
// Play: https://go.dev/play/p/wadzrWr9Aer
func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) R) R {

if collection == nil {
return 0
}

if len(collection) == 0 {
return 0
}

var product R = 1
for i := range collection {
product = product * iteratee(collection[i])
}
return product
}

// Mean calculates the mean of a collection of numbers.
func Mean[T constraints.Float | constraints.Integer](collection []T) T {
var length = T(len(collection))
Expand Down
40 changes: 40 additions & 0 deletions math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,46 @@ func TestSumBy(t *testing.T) {
is.Equal(result5, complex128(6_6))
}

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

result1 := Product([]float32{2.3, 3.3, 4, 5.3})
result2 := Product([]int32{2, 3, 4, 5})
result3 := Product([]int32{7, 8, 9, 0})
result4 := Product([]int32{7, -1, 9, 2})
result5 := Product([]uint32{2, 3, 4, 5})
result6 := Product([]uint32{})
result7 := Product([]complex128{4_4, 2_2})

is.Equal(result1, float32(160.908))
is.Equal(result2, int32(120))
is.Equal(result3, int32(0))
is.Equal(result4, int32(-126))
is.Equal(result5, uint32(120))
is.Equal(result6, uint32(0))
is.Equal(result7, complex128(96_8))
}

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

result1 := ProductBy([]float32{2.3, 3.3, 4, 5.3}, func(n float32) float32 { return n })
result2 := ProductBy([]int32{2, 3, 4, 5}, func(n int32) int32 { return n })
result3 := ProductBy([]int32{7, 8, 9, 0}, func(n int32) int32 { return n })
result4 := ProductBy([]int32{7, -1, 9, 2}, func(n int32) int32 { return n })
result5 := ProductBy([]uint32{2, 3, 4, 5}, func(n uint32) uint32 { return n })
result6 := ProductBy([]uint32{}, func(n uint32) uint32 { return n })
result7 := ProductBy([]complex128{4_4, 2_2}, func(n complex128) complex128 { return n })

is.Equal(result1, float32(160.908))
is.Equal(result2, int32(120))
is.Equal(result3, int32(0))
is.Equal(result4, int32(-126))
is.Equal(result5, uint32(120))
is.Equal(result6, uint32(0))
is.Equal(result7, complex128(96_8))
}

func TestMean(t *testing.T) {
t.Parallel()
is := assert.New(t)
Expand Down

0 comments on commit 9587591

Please sign in to comment.