Repository: elliotchance/pie
Pull request #109 (2019-05-07 00:01:22)

Implement product function
See #69

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/elliotchance/pie/109)
<!-- Reviewable:end -->


codecov-io: # [Codecov](https://codecov.io/gh/elliotchance/pie/pull/109?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@7ff9a21`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/elliotchance/pie/pull/109/graphs/tree.svg?width=650&token=OvugwUQGM3&height=150&src=pr)](https://codecov.io/gh/elliotchance/pie/pull/109?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##             master   #109   +/-   ##
=======================================
  Coverage          ?   100%           
=======================================
  Files             ?      7           
  Lines             ?    854           
  Branches          ?      0           
=======================================
  Hits              ?    854           
  Misses            ?      0           
  Partials          ?      0
```


| [Impacted Files](https://codecov.io/gh/elliotchance/pie/pull/109?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pie/float64s\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/109/diff?src=pr&el=tree#diff-cGllL2Zsb2F0NjRzX3BpZS5nbw==) | `100% <100%> (ø)` | |
| [pie/ints\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/109/diff?src=pr&el=tree#diff-cGllL2ludHNfcGllLmdv) | `100% <100%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/elliotchance/pie/pull/109?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/elliotchance/pie/pull/109?src=pr&el=footer). Last update [7ff9a21...fbf5eed](https://codecov.io/gh/elliotchance/pie/pull/109?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index aef4656..354dfb8 100644
--- a/README.md
+++ b/README.md
@@ -150,6 +150,7 @@ This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Filter`.
 | `Max`        | ✓      | ✓      |       |      | n        | The maximum value, or a zeroes value. |
 | `Median`     |        | ✓      |       |      | n⋅log(n) | Median returns the value separating the higher half from the lower half of a data sample. |
 | `Min`        | ✓      | ✓      |       |      | n        | The minimum value, or a zeroed value. |
+| `Product`    |        | ✓      |       |      | n        | Product of all elements. |
 | `Random`     | ✓      | ✓      | ✓     |      | 1        | Select a random element, or a zeroed value if empty. |
 | `Reverse`    | ✓      | ✓      | ✓     |      | n        | Reverse elements. |
 | `Send`     | ✓      | ✓      | ✓     |      | n        | Send all element to channel. |
diff --git a/functions/main.go b/functions/main.go
index a7618e7..1099436 100644
--- a/functions/main.go
+++ b/functions/main.go
@@ -44,6 +44,7 @@ var Functions = []struct {
 	{"Max", "max.go", ForNumbersAndStrings},
 	{"Median", "median.go", ForNumbers},
 	{"Min", "min.go", ForNumbersAndStrings},
+	{"Product", "product.go", ForNumbers},
 	{"Random", "random.go", ForAll},
 	{"Reverse", "reverse.go", ForAll},
 	{"Send", "send.go", ForAll},
diff --git a/functions/product.go b/functions/product.go
new file mode 100644
index 0000000..1b538fc
--- /dev/null
+++ b/functions/product.go
@@ -0,0 +1,14 @@
+package functions
+
+// Product is the product of all of the elements.
+func (ss SliceType) Product() (product ElementType) {
+	if len(ss) == 0 {
+		return
+	}
+	product = ss[0]
+	for _, s := range ss[1:] {
+		product *= s
+	}
+
+	return
+}
diff --git a/pie/float64s_pie.go b/pie/float64s_pie.go
index 4621adc..cb286e9 100755
--- a/pie/float64s_pie.go
+++ b/pie/float64s_pie.go
@@ -330,6 +330,19 @@ func (ss Float64s) Min() (min float64) {
 	return
 }
 
+// Product is the product of all of the elements.
+func (ss Float64s) Product() (product float64) {
+	if len(ss) == 0 {
+		return
+	}
+	product = ss[0]
+	for _, s := range ss[1:] {
+		product *= s
+	}
+
+	return
+}
+
 // Random returns a random element by your rand.Source, or zero
 func (ss Float64s) Random(source rand.Source) float64 {
 	n := len(ss)
diff --git a/pie/ints_pie.go b/pie/ints_pie.go
index b1bb76f..e8fa45d 100755
--- a/pie/ints_pie.go
+++ b/pie/ints_pie.go
@@ -330,6 +330,19 @@ func (ss Ints) Min() (min int) {
 	return
 }
 
+// Product is the product of all of the elements.
+func (ss Ints) Product() (product int) {
+	if len(ss) == 0 {
+		return
+	}
+	product = ss[0]
+	for _, s := range ss[1:] {
+		product *= s
+	}
+
+	return
+}
+
 // Random returns a random element by your rand.Source, or zero
 func (ss Ints) Random(source rand.Source) int {
 	n := len(ss)
diff --git a/template.go b/template.go
index 34c5805..b282e93 100644
--- a/template.go
+++ b/template.go
@@ -419,6 +419,21 @@ func (ss SliceType) Min() (min ElementType) {
 
 	return
 }
+`,
+	"Product": `package functions
+
+// Product is the product of all of the elements.
+func (ss SliceType) Product() (product ElementType) {
+	if len(ss) == 0 {
+		return
+	}
+	product = ss[0]
+	for _, s := range ss[1:] {
+		product *= s
+	}
+
+	return
+}
 `,
 	"Random": `package functions
 


Test patch:
diff --git a/pie/float64s_test.go b/pie/float64s_test.go
index d334b9b..bcb0902 100644
--- a/pie/float64s_test.go
+++ b/pie/float64s_test.go
@@ -161,10 +161,10 @@ func TestFloat64s_Last(t *testing.T) {
 }
 
 var float64sStatsTests = []struct {
-	ss            Float64s
-	min, max, sum float64
-	len           int
-	average       float64
+	ss                     Float64s
+	min, max, sum, product float64
+	len                    int
+	average                float64
 }{
 	{
 		nil,
@@ -173,6 +173,7 @@ var float64sStatsTests = []struct {
 		0,
 		0,
 		0,
+		0,
 	},
 	{
 		[]float64{},
@@ -181,12 +182,14 @@ var float64sStatsTests = []struct {
 		0,
 		0,
 		0,
+		0,
 	},
 	{
 		[]float64{1.5},
 		1.5,
 		1.5,
 		1.5,
+		1.5,
 		1,
 		1.5,
 	},
@@ -195,6 +198,7 @@ var float64sStatsTests = []struct {
 		1.9,
 		5.1,
 		12.3,
+		66.0858,
 		4,
 		3.075,
 	},
@@ -227,6 +231,15 @@ func TestFloat64s_Sum(t *testing.T) {
 	}
 }
 
+func TestFloat64s_Product(t *testing.T) {
+	for _, test := range float64sStatsTests {
+		t.Run("", func(t *testing.T) {
+			defer assertImmutableFloat64s(t, &test.ss)()
+			assert.Equal(t, test.product, Float64s(test.ss).Product())
+		})
+	}
+}
+
 func TestFloat64s_Len(t *testing.T) {
 	for _, test := range float64sStatsTests {
 		t.Run("", func(t *testing.T) {
diff --git a/pie/ints_test.go b/pie/ints_test.go
index ade3d52..686913b 100644
--- a/pie/ints_test.go
+++ b/pie/ints_test.go
@@ -153,9 +153,9 @@ func TestInts_Last(t *testing.T) {
 }
 
 var intsStatsTests = []struct {
-	ss                 []int
-	min, max, sum, len int
-	average            float64
+	ss                          []int
+	min, max, sum, product, len int
+	average                     float64
 }{
 	{
 		nil,
@@ -164,6 +164,7 @@ var intsStatsTests = []struct {
 		0,
 		0,
 		0,
+		0,
 	},
 	{
 		[]int{},
@@ -172,6 +173,7 @@ var intsStatsTests = []struct {
 		0,
 		0,
 		0,
+		0,
 	},
 	{
 		[]int{1},
@@ -180,12 +182,14 @@ var intsStatsTests = []struct {
 		1,
 		1,
 		1,
+		1,
 	},
 	{
 		[]int{2, 3, 5, 1},
 		1,
 		5,
 		11,
+		30,
 		4,
 		2.75,
 	},
@@ -215,6 +219,14 @@ func TestInts_Sum(t *testing.T) {
 	}
 }
 
+func TestInts_Product(t *testing.T) {
+	for _, test := range intsStatsTests {
+		t.Run("", func(t *testing.T) {
+			assert.Equal(t, test.product, Ints(test.ss).Product())
+		})
+	}
+}
+
 func TestInts_Len(t *testing.T) {
 	for _, test := range intsStatsTests {
 		t.Run("", func(t *testing.T) {