Skip to content

Commit 1c1dfd9

Browse files
feat: add Product and ProductBy functions (#566)
Co-authored-by: [email protected] <[email protected]>
1 parent 124d300 commit 1c1dfd9

File tree

3 files changed

+112
-3
lines changed

3 files changed

+112
-3
lines changed

README.md

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ Supported math helpers:
155155
- [Clamp](#clamp)
156156
- [Sum](#sum)
157157
- [SumBy](#sumby)
158+
- [Product](#product)
159+
- [ProductBy](#productby)
158160
- [Mean](#mean)
159161
- [MeanBy](#meanby)
160162

@@ -866,7 +868,6 @@ l := lo.DropByIndex([]int{0, 1, 2, 3, 4, 5}, 2, 4, -1)
866868

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

869-
870871
### Reject
871872

872873
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 {
885886
The opposite of FilterMap, this method returns a slice which obtained after both filtering and mapping using the given callback function.
886887

887888
The callback function should return two values:
889+
888890
- the result of the mapping operation and
889891
- whether the result element should be included or not.
890892

@@ -1511,7 +1513,35 @@ sum := lo.SumBy(strings, func(item string) int {
15111513
// 6
15121514
```
15131515

1514-
[[play](https://go.dev/play/p/Dz_a_7jN_ca)]
1516+
### Product
1517+
1518+
Calculates the product of the values in a collection.
1519+
1520+
If collection is empty 0 is returned.
1521+
1522+
```go
1523+
list := []int{1, 2, 3, 4, 5}
1524+
product := lo.Product(list)
1525+
// 120
1526+
```
1527+
1528+
[[play](https://go.dev/play/p/2_kjM_smtAH)]
1529+
1530+
### ProductBy
1531+
1532+
Calculates the product of the values in a collection using the given return value from the iteration function.
1533+
1534+
If collection is empty 0 is returned.
1535+
1536+
```go
1537+
strings := []string{"foo", "bar"}
1538+
product := lo.ProductBy(strings, func(item string) int {
1539+
return len(item)
1540+
})
1541+
// 9
1542+
```
1543+
1544+
[[play](https://go.dev/play/p/wadzrWr9Aer)]
15151545

15161546
### Mean
15171547

@@ -2693,6 +2723,7 @@ first := lo.FirstOrEmpty([]int{1, 2, 3})
26932723
first := lo.FirstOrEmpty([]int{})
26942724
// 0
26952725
```
2726+
26962727
### FirstOr
26972728

26982729
Returns the first element of a collection or the fallback value if empty.
@@ -2730,6 +2761,7 @@ last := lo.LastOrEmpty([]int{1, 2, 3})
27302761
last := lo.LastOrEmpty([]int{})
27312762
// 0
27322763
```
2764+
27332765
### LastOr
27342766

27352767
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
36443676
// false
36453677
```
36463678

3647-
36483679
### WaitForWithContext
36493680

36503681
Runs periodically until a condition is validated or context is invalid.

math.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,44 @@ func SumBy[T any, R constraints.Float | constraints.Integer | constraints.Comple
8585
return sum
8686
}
8787

88+
// Product gets the product of the values in a collection. If collection is empty 0 is returned.
89+
// Play: https://go.dev/play/p/2_kjM_smtAH
90+
func Product[T constraints.Float | constraints.Integer | constraints.Complex](collection []T) T {
91+
92+
if collection == nil {
93+
return 0
94+
}
95+
96+
if len(collection) == 0 {
97+
return 0
98+
}
99+
100+
var product T = 1
101+
for i := range collection {
102+
product *= collection[i]
103+
}
104+
return product
105+
}
106+
107+
// ProductBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 0 is returned.
108+
// Play: https://go.dev/play/p/wadzrWr9Aer
109+
func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) R) R {
110+
111+
if collection == nil {
112+
return 0
113+
}
114+
115+
if len(collection) == 0 {
116+
return 0
117+
}
118+
119+
var product R = 1
120+
for i := range collection {
121+
product = product * iteratee(collection[i])
122+
}
123+
return product
124+
}
125+
88126
// Mean calculates the mean of a collection of numbers.
89127
func Mean[T constraints.Float | constraints.Integer](collection []T) T {
90128
var length = T(len(collection))

math_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,46 @@ func TestSumBy(t *testing.T) {
9898
is.Equal(result5, complex128(6_6))
9999
}
100100

101+
func TestProduct(t *testing.T) {
102+
is := assert.New(t)
103+
104+
result1 := Product([]float32{2.3, 3.3, 4, 5.3})
105+
result2 := Product([]int32{2, 3, 4, 5})
106+
result3 := Product([]int32{7, 8, 9, 0})
107+
result4 := Product([]int32{7, -1, 9, 2})
108+
result5 := Product([]uint32{2, 3, 4, 5})
109+
result6 := Product([]uint32{})
110+
result7 := Product([]complex128{4_4, 2_2})
111+
112+
is.Equal(result1, float32(160.908))
113+
is.Equal(result2, int32(120))
114+
is.Equal(result3, int32(0))
115+
is.Equal(result4, int32(-126))
116+
is.Equal(result5, uint32(120))
117+
is.Equal(result6, uint32(0))
118+
is.Equal(result7, complex128(96_8))
119+
}
120+
121+
func TestProductBy(t *testing.T) {
122+
is := assert.New(t)
123+
124+
result1 := ProductBy([]float32{2.3, 3.3, 4, 5.3}, func(n float32) float32 { return n })
125+
result2 := ProductBy([]int32{2, 3, 4, 5}, func(n int32) int32 { return n })
126+
result3 := ProductBy([]int32{7, 8, 9, 0}, func(n int32) int32 { return n })
127+
result4 := ProductBy([]int32{7, -1, 9, 2}, func(n int32) int32 { return n })
128+
result5 := ProductBy([]uint32{2, 3, 4, 5}, func(n uint32) uint32 { return n })
129+
result6 := ProductBy([]uint32{}, func(n uint32) uint32 { return n })
130+
result7 := ProductBy([]complex128{4_4, 2_2}, func(n complex128) complex128 { return n })
131+
132+
is.Equal(result1, float32(160.908))
133+
is.Equal(result2, int32(120))
134+
is.Equal(result3, int32(0))
135+
is.Equal(result4, int32(-126))
136+
is.Equal(result5, uint32(120))
137+
is.Equal(result6, uint32(0))
138+
is.Equal(result7, complex128(96_8))
139+
}
140+
101141
func TestMean(t *testing.T) {
102142
t.Parallel()
103143
is := assert.New(t)

0 commit comments

Comments
 (0)