From 0d42f88484c312159c922a25ea2bf5694a8d1eba Mon Sep 17 00:00:00 2001 From: Thuc Le Date: Sun, 2 Jan 2022 19:40:17 +0100 Subject: [PATCH] Update document + correct group function --- README.md | 32 ++++++++++++++++---------------- doc.go | 2 ++ errors.go | 1 + every.go | 1 + exist.go | 1 + filter.go | 1 + find.go | 1 + flat.go | 1 + foreach.go | 1 + group.go | 10 ++++++++-- group_test.go | 4 ++-- map.go | 1 + reduce.go | 4 ++++ reduce_right.go | 4 ++++ some.go | 1 + 15 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 doc.go diff --git a/README.md b/README.md index 314e14c..0ba26c8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![goterators-Thumbnail](https://user-images.githubusercontent.com/1828895/147876484-5bc7cfd0-5f14-4889-a3f0-64cb307b7765.png) - - Goterators is util library that Supports aggregate & transforms functions Go, including: + - Goterators is util library that support aggregate & transforms functions list in Go, including: - [for-each](#for-each) - [find](#find) - [exist](#exist) @@ -15,7 +15,7 @@ - [some](#some) - [flat](#flat) - - API and functions are inspired from Rust and Javascript. + - The API and functions are inspired by Rust and Javascript. # Requirement @@ -45,7 +45,7 @@ import "github.com/ledongthuc/goterators" ![goterators-ForEach](https://user-images.githubusercontent.com/1828895/147876359-432c3122-25f3-492e-844d-6172eafe92a6.png) - - For-each function act the same `for` in Go. Just another option to loop through items in a list. + - For-each function does the same `for` in Go. Just another option to loop through items in a list. ```go ForEach(list1, func(item int) { @@ -65,7 +65,7 @@ ForEach(list3, func(item MyStruct) { ![goterators-Find](https://user-images.githubusercontent.com/1828895/147876363-245705c5-2aa8-4135-8d29-5cbaca173529.png) - - Find function return first element and its index in the list that meets function condition. In case no element meet the condition function, return the error "Not Found". + - Find function returns the first element and its index in the list that meets the functional condition. If no element meet the condition function, return the error "Not Found". ```go matchedInt, index, err := Find(list, func(item int) bool { @@ -85,7 +85,7 @@ matchedStruct, index, err := Find(list, func(item MyStruct) bool { ![goterators-Exist](https://user-images.githubusercontent.com/1828895/147876367-c0c7fd50-1888-4152-a7c8-5960ca26b6d9.png) - - Exist check an existence of element in the list + - Exist function checks the existence of an element in the list. ```go matchedInt, err := Exist(list, 1) @@ -99,11 +99,11 @@ matchedStruct, err := Exist(list, SearchingStruct) ![goterators-Reduce](https://user-images.githubusercontent.com/1828895/147876373-4cb1f784-b9d4-4b95-a4f9-30709ba3690d.png) - - Similar to Fold Left, Reduce function run the reducer function on each element of array. In order, the reduce function passes in the return value from calculation on the preceding element. The final result of running the reducer across all elements of the array is the return value of final reducer on last element. + - Similar to Fold Left, Reduce function runs the reducer function on each element of the array. In order, the reduce function passes in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is the return value of the final reducer on the last element. - Reduce function has 3 parameters: - list: source list we want to process. - - initial value: the previous value that's used in reducer call of first element. At this time, previous = initial value, current = first element of list. - - reducer function: the function will run on all elements of source list. + - 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. ```go // Sum @@ -121,11 +121,11 @@ items := Reduce(testSource, []float64{}, func(previous []float64, current int, i ![goterators-Reduce right](https://user-images.githubusercontent.com/1828895/147876376-1f168d48-3ba5-4d44-aa0a-4e1c36505be5.png) - - Similar to Fold Right, Reduce function run the reducer function on each element of array, from last to first element. In order, the reduce function passes in the return value from calculation on the preceding element. The final result of running the reducer across all elements of the array is the return value of final reducer on first element. + - Similar to Fold Right, Reduce right function run the reducer function on each element of the array, from last to the first element. In order, the reduce function passes in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is the return value of the final reducer on the first element. - Reduce function has 3 parameters: - list: source list we want to process. - - initial value: the previous value that's used in reducer call of last element. At this time, previous = initial value, current = last element of list. - - reducer function: the function will run on all elements of source list. + - 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. ```go // Reverse @@ -138,7 +138,7 @@ reversedList := Reduce(list, []string{}, func(previous []string, current string, ![goterators-Filter](https://user-images.githubusercontent.com/1828895/147876377-6df6ea14-6fb7-478c-9671-e6ca7c6e2a97.png) - - Filter function filters items that meets function condition + - Filter function return items that pass the filter function. ```go filteredItems, err := Filter(list, func(item int) bool { @@ -158,7 +158,7 @@ filteredItems, err := Filter(list, func(item MyStruct) bool { ![goterators-Map](https://user-images.githubusercontent.com/1828895/147876383-5d701c6e-fb65-442f-b5ed-e97d30c23115.png) - - Map function convert items in the list to output list + - Map function converts items in the list to the output list. ```go mappedItems := Map(testSource, func(item int64) float64 { @@ -174,7 +174,7 @@ prices := Map(testSource, func(item Order) Price { ![goterators-Every](https://user-images.githubusercontent.com/1828895/147876387-520ee3b5-2846-4052-ad35-dd57d8741bd1.png) - - Every function check all elements in the list meet the condition, return true. Otherwise, return false. + - Every function checks all elements in the list with condition function. If it's yes return true; otherwise, return false. ```go valid := Every(list, func(item int) bool { item % 2 == 0 }) @@ -198,7 +198,7 @@ valid := Some(list, func(item string) bool { len(item) < 20 }) ![goterators-Group](https://user-images.githubusercontent.com/1828895/147878206-bef39880-96db-4269-b54e-2dcbb06f6bac.png) - - Group function group elements into nested list by group condition. + - Group groups elements into the nested level. Use a build-group function to define group type. ``` groups := Group(list, func(item Product) groupKey { @@ -210,7 +210,7 @@ groups := Group(list, func(item Product) groupKey { ![goterators-Flat](https://user-images.githubusercontent.com/1828895/147876403-25e84044-d761-45b7-b126-6ad8a7c5a4d1.png) - - Flat function return new array with all sub-array elements concatenated with 1 level depth. + - Flat returns a new array with all sub-array elements concatenated with 1 level depth. ```go output := Flat([][]int{{1,2}, {3}}) // output = {1,2,3} diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..2a2d6ca --- /dev/null +++ b/doc.go @@ -0,0 +1,2 @@ +// Package goterators provides utility functions that support aggregate & transforms list in Go. +package goterators diff --git a/errors.go b/errors.go index 73567f4..3f70632 100644 --- a/errors.go +++ b/errors.go @@ -3,5 +3,6 @@ package goterators import "fmt" var ( + // ErrNotFound is used in functions that need to find any items in the list but are not found. ErrNotFound = fmt.Errorf("not found") ) diff --git a/every.go b/every.go index 2ecf6ad..c106808 100644 --- a/every.go +++ b/every.go @@ -1,5 +1,6 @@ package goterators +// Every checks all elements in the list with condition function. If it's yes return true; otherwise, return false. func Every[T comparable](source []T, conditionFunc func(item T) bool) bool { for _, item := range source { if !conditionFunc(item) { diff --git a/exist.go b/exist.go index 8f6f59f..dbb9f48 100644 --- a/exist.go +++ b/exist.go @@ -1,5 +1,6 @@ package goterators +// Exist checks the existence of an element in the list. func Exist[T comparable](source []T, checkingItem T) bool { _, _, err := Find[T](source, func(item T) bool { return item == checkingItem diff --git a/filter.go b/filter.go index 11cde0a..4d998d2 100644 --- a/filter.go +++ b/filter.go @@ -1,5 +1,6 @@ package goterators +// Filter return items that pass the filter function. func Filter[T any](source []T, filteredFunc func(item T) bool) (output []T) { for _, item := range source { if filteredFunc(item) { diff --git a/find.go b/find.go index fbaf47f..7556ecf 100644 --- a/find.go +++ b/find.go @@ -1,5 +1,6 @@ package goterators +// Find returns the first element and its index in the list that meets the functional condition. If no element meet the condition function, return the error "Not Found". func Find[T any](source []T, matchedItemFunc func(item T) bool) (t T, index int, err error) { for index, item := range source { if matchedItemFunc(item) { diff --git a/flat.go b/flat.go index 25391b5..4179c6e 100644 --- a/flat.go +++ b/flat.go @@ -1,5 +1,6 @@ package goterators +// Flat returns a new array with all sub-array elements concatenated with 1 level depth. func Flat[T any](source [][]T) []T { outputSize := 0 for _, group := range source { diff --git a/foreach.go b/foreach.go index e75bb2e..39734b1 100644 --- a/foreach.go +++ b/foreach.go @@ -1,5 +1,6 @@ package goterators +// ForEach does the same `for` in Go. Just another option to loop through items in a list. func ForEach[T any](source []T, handler func(item T)) { for _, item := range source { handler(item) diff --git a/group.go b/group.go index c051dff..4c816c6 100644 --- a/group.go +++ b/group.go @@ -1,10 +1,16 @@ package goterators +// Group groups elements into the nested level. Use a build-group function to define group type. func Group[T any, G comparable](source []T, buildGroup func(item T) G) [][]T { - output := map[G][]T{} + m := map[G][]T{} for index, item := range source { group := buildGroup(item) - output[group] = append(output[group], source[index]) + m[group] = append(m[group], source[index]) + } + + output := make([][]T, 0, len(m)) + for key := range m { + output = append(output, m[key]) } return output } diff --git a/group_test.go b/group_test.go index a5aa015..4f3d0ed 100644 --- a/group_test.go +++ b/group_test.go @@ -49,11 +49,11 @@ func TestGroup(t *testing.T) { } for groupIndex := range expectedItems { if len(expectedItems[groupIndex]) != len(actualItems[groupIndex]) { - t.Fatalf("Group index %v, expected = %v, actual = %v", groupIndex, expectedItems[key], actualItems[key]) + t.Fatalf("Group index %v, expected = %v, actual = %v", groupIndex, expectedItems[groupIndex], actualItems[groupIndex]) } for index := range expectedItems[groupIndex] { if expectedItems[groupIndex][index] != actualItems[groupIndex][index] { - t.Errorf("Group index %v, Index %v, expected = %v, actual = %v", groupIndex, index, expectedItems[key][index], actualItems[key][index]) + t.Errorf("Group index %v, Index %v, expected = %v, actual = %v", groupIndex, index, expectedItems[groupIndex][index], actualItems[groupIndex][index]) } } } diff --git a/map.go b/map.go index aa6ce1b..a828e70 100644 --- a/map.go +++ b/map.go @@ -1,5 +1,6 @@ package goterators +// Map function converts items in the list to the output list. func Map[T1 any, T2 any](source []T1, mappingFunc func(item T1) T2) (output []T2) { for _, item := range source { output = append(output, mappingFunc(item)) diff --git a/reduce.go b/reduce.go index 21f2ae6..4c1151c 100644 --- a/reduce.go +++ b/reduce.go @@ -1,5 +1,9 @@ package goterators +/*Reduce runs the reducer function on each element of the array. In order, the reduce function passes in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is the return value of the final reducer on the last element. +- list paramerter: source list we want to process. +- initial value paramerter: 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 paramerter: the function will run on all elements of the source list.*/ func Reduce[T1 any, T2 any](source []T1, initialValue T2, reducer func(previousValue T2, currentValue T1, currentIndex int, list []T1) T2) T2 { previousItem := initialValue output := initialValue diff --git a/reduce_right.go b/reduce_right.go index 95ded96..9cd6ca5 100644 --- a/reduce_right.go +++ b/reduce_right.go @@ -1,5 +1,9 @@ package goterators +/* ReduceRight runs the reducer function on each element of the array, from last to the first element. In order, the reduce function passes in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is the return value of the final reducer on the first element. +- list parameter: source list we want to process. +- initial value parameter: 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 parameter: the function will run on all elements of the source list.*/ func ReduceRight[T1 any, T2 any](source []T1, initialValue T2, reducer func(previousValue T2, currentValue T1, currentIndex int, list []T1) T2) T2 { previousItem := initialValue output := initialValue diff --git a/some.go b/some.go index 1b0e71b..1ad367b 100644 --- a/some.go +++ b/some.go @@ -1,5 +1,6 @@ package goterators +// Some checks at least one element in the list meet the condition; return true, or return false if all elements don't meet the condition. func Some[T comparable](source []T, conditionFunc func(item T) bool) bool { for _, item := range source { if conditionFunc(item) {