From 0459cd076494ab920a9672693d10b12ea21b54cf Mon Sep 17 00:00:00 2001 From: Thuc Le Date: Wed, 5 Jan 2022 20:44:25 +0100 Subject: [PATCH] Add Sum() and Average() --- README.md | 29 +++++++++++++++++++++++++++++ average.go | 14 ++++++++++++++ average_test.go | 27 +++++++++++++++++++++++++++ constraints.go | 7 +++++++ reduce.go | 10 ++++++++++ reduce_right.go | 5 +++++ sum.go | 9 +++++++++ sum_test.go | 21 +++++++++++++++++++++ 8 files changed, 122 insertions(+) create mode 100644 average.go create mode 100644 average_test.go create mode 100644 constraints.go create mode 100644 sum.go create mode 100644 sum_test.go diff --git a/README.md b/README.md index dffa936..f4474e4 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,10 @@ - [exist](#exist) - [include](#include) - [include some](#include-some) + - [sum](#sum) + - [average](#average) + - Support generic functions that fit with all your types. - The API and functions are inspired by Rust and Javascript. # Requirement @@ -93,6 +96,7 @@ matchedStruct, index, err := Find(list, func(item MyStruct) bool { - list: source list we want to process. - initial value: the previous value that's used in the reducer call of the first element. At this time, previous = initial value, current = first element of the list. - reducer function: the function will run on all elements of the source list. + - Can use Reduce() or ReduceLeft() or FoldLeft() ```go // Sum @@ -115,6 +119,7 @@ items := Reduce(testSource, []float64{}, func(previous []float64, current int, i - list: source list we want to process. - initial value: the previous value that's used in the reducer call of the last element. At this time, previous = initial value, current = last element of list. - reducer function: the function will run on all elements of the source list. + - Can use ReduceRight() or FoldRight() ```go // Reverse @@ -245,6 +250,30 @@ result := IncludeSome(list, subList) fmt.Println("IncludeSome: ", result) ``` +## Sum + +![goterators-Sum](https://user-images.githubusercontent.com/1828895/148277403-70da16a7-5314-42d0-a9bf-c59bc3f0cba5.png) + + - Sum plus all item from source list + +```go +testSource := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} +fmt.Println("Sum: ", Sum(testSource)) +``` + +## Average + +![goterators-Average](https://user-images.githubusercontent.com/1828895/148277508-66a08f9e-22ec-4e04-8808-69bee8649871.png) + + - Average sum of all the source list divided by the total number of source list + - We can use Average() or Mean() + +```go +testSource := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} +fmt.Println("Average: ", Average(testSource)) +fmt.Println("Mean: ", Mean(testSource)) +``` + # License MIT diff --git a/average.go b/average.go new file mode 100644 index 0000000..6d55bf1 --- /dev/null +++ b/average.go @@ -0,0 +1,14 @@ +package goterators + +// Average sum of all the source list divided by the total number of source list +func Average[T Number](source []T) float64 { + var sum T + for _, item := range source { + sum += item + } + return float64(sum) / float64(len(source)) +} + +func Mean[T Number](source []T) float64 { + return Average(source) +} diff --git a/average_test.go b/average_test.go new file mode 100644 index 0000000..d71da54 --- /dev/null +++ b/average_test.go @@ -0,0 +1,27 @@ +package goterators + +import ( + "fmt" + "testing" +) + +func TestAverage(t *testing.T) { + testSource := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} + expectedValue := 10.5 + + actutalValue := Average(testSource) + if actutalValue != expectedValue { + t.Errorf("Expected = %v , got = %v", expectedValue, actutalValue) + } + + actutalValue = Mean(testSource) + if actutalValue != expectedValue { + t.Errorf("Expected = %v , got = %v", expectedValue, actutalValue) + } +} + +func ExampleAverage() { + testSource := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} + fmt.Println("Average: ", Average(testSource)) + fmt.Println("Mean: ", Mean(testSource)) +} diff --git a/constraints.go b/constraints.go new file mode 100644 index 0000000..cb33a71 --- /dev/null +++ b/constraints.go @@ -0,0 +1,7 @@ +package goterators + +import "constraints" + +type Number interface { + constraints.Integer | constraints.Float +} diff --git a/reduce.go b/reduce.go index 4c1151c..34e24cc 100644 --- a/reduce.go +++ b/reduce.go @@ -13,3 +13,13 @@ func Reduce[T1 any, T2 any](source []T1, initialValue T2, reducer func(previousV } return output } + +// ReduceLeft is same with Reduce() +func ReduceLeft[T1 any, T2 any](source []T1, initialValue T2, reducer func(previousValue T2, currentValue T1, currentIndex int, list []T1) T2) T2 { + return Reduce(source, initialValue, reducer) +} + +// FoldLeft is same with Reduce() +func FoldLeft[T1 any, T2 any](source []T1, initialValue T2, reducer func(previousValue T2, currentValue T1, currentIndex int, list []T1) T2) T2 { + return Reduce(source, initialValue, reducer) +} diff --git a/reduce_right.go b/reduce_right.go index 9cd6ca5..3847e12 100644 --- a/reduce_right.go +++ b/reduce_right.go @@ -13,3 +13,8 @@ func ReduceRight[T1 any, T2 any](source []T1, initialValue T2, reducer func(prev } return output } + +// FoldRight is same with Reduce() +func FoldRight[T1 any, T2 any](source []T1, initialValue T2, reducer func(previousValue T2, currentValue T1, currentIndex int, list []T1) T2) T2 { + return Reduce(source, initialValue, reducer) +} diff --git a/sum.go b/sum.go new file mode 100644 index 0000000..37a190a --- /dev/null +++ b/sum.go @@ -0,0 +1,9 @@ +package goterators + +// Sum plus all item from source list +func Sum[T Number](source []T) (result T) { + for _, item := range source { + result += item + } + return result +} diff --git a/sum_test.go b/sum_test.go new file mode 100644 index 0000000..a04ef81 --- /dev/null +++ b/sum_test.go @@ -0,0 +1,21 @@ +package goterators + +import ( + "fmt" + "testing" +) + +func TestSum(t *testing.T) { + testSource := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} + expectedValue := 210 + actutalValue := Sum(testSource) + + if actutalValue != expectedValue { + t.Errorf("Expected = %v , got = %v", expectedValue, actutalValue) + } +} + +func ExampleSum() { + testSource := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} + fmt.Println("Sum: ", Sum(testSource)) +}