feat: add Product and ProductBy functions (#566)

Co-authored-by: John.Devitt@cdp.net <JohnDevitt@Mac.cust.communityfibre.co.uk>
This commit is contained in:
JohnDevitt
2025-01-27 01:02:11 +01:00
committed by GitHub
parent 124d3004de
commit 1c1dfd9d29
3 changed files with 112 additions and 3 deletions
+34 -3
View File
@@ -155,6 +155,8 @@ Supported math helpers:
- [Clamp](#clamp)
- [Sum](#sum)
- [SumBy](#sumby)
- [Product](#product)
- [ProductBy](#productby)
- [Mean](#mean)
- [MeanBy](#meanby)
@@ -866,7 +868,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.
@@ -885,6 +886,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.
@@ -1511,7 +1513,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}
product := 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"}
product := lo.ProductBy(strings, func(item string) int {
return len(item)
})
// 9
```
[[play](https://go.dev/play/p/wadzrWr9Aer)]
### Mean
@@ -2693,6 +2723,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.
@@ -2730,6 +2761,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.
@@ -3644,7 +3676,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.
+38
View File
@@ -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))
+40
View File
@@ -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)