diff --git a/README.md b/README.md index c0852b50..3396c481 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ In the future, 5 to 10 helpers will overlap with those coming into the Go standa **Why this name?** -I wanted a **short name**, similar to "Lodash" and no Go package currently uses this name. +I wanted a **short name**, similar to "Lodash" and no Go package uses this name. ![lo](img/logo-full.png) @@ -54,7 +54,7 @@ import ( Then use one of the helpers below: ```go -names := lo.Uniq[string]([]string{"Samuel", "John", "Samuel"}) +names := lo.Uniq([]string{"Samuel", "John", "Samuel"}) // []string{"Samuel", "John"} ``` @@ -894,7 +894,7 @@ Returns a slice of all non-zero elements. ```go in := []string{"", "foo", "", "bar", ""} -slice := lo.Compact[string](in) +slice := lo.Compact(in) // []string{"foo", "bar"} ``` @@ -929,7 +929,7 @@ slice := lo.IsSortedByKey([]string{"a", "bb", "ccc"}, func(s string) int { Creates an array of the map keys. ```go -keys := lo.Keys[string, int](map[string]int{"foo": 1, "bar": 2}) +keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}) // []string{"foo", "bar"} ``` @@ -951,10 +951,10 @@ values := lo.Values[string, int](map[string]int{"foo": 1, "bar": 2}) Returns the value of the given key or the fallback value if the key is not present. ```go -value := lo.ValueOr[string, int](map[string]int{"foo": 1, "bar": 2}, "foo", 42) +value := lo.ValueOr(map[string]int{"foo": 1, "bar": 2}, "foo", 42) // 1 -value := lo.ValueOr[string, int](map[string]int{"foo": 1, "bar": 2}, "baz", 42) +value := lo.ValueOr(map[string]int{"foo": 1, "bar": 2}, "baz", 42) // 42 ``` @@ -1089,7 +1089,7 @@ m2 := lo.Invert(map[string]int{"a": 1, "b": 2, "c": 1}) Merges multiple maps from left to right. ```go -mergedMaps := lo.Assign[string, int]( +mergedMaps := lo.Assign( map[string]int{"a": 1, "b": 2}, map[string]int{"b": 3, "c": 4}, ) @@ -1344,6 +1344,19 @@ tuples := lo.Zip2([]string{"a", "b"}, []int{1, 2}) [[play](https://go.dev/play/p/jujaA6GaJTp)] +### ZipBy2 -> ZipBy9 + +ZipBy creates a slice of transformed elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on. + +When collections have different size, the Tuple attributes are filled with zero value. + +```go +items := lo.ZipBy2([]string{"a", "b"}, []int{1, 2}, func(a string, b int) string { + return fmt.Sprintf("%s-%d", a, b) +}) +// []string{"a-1", "b-2"} +``` + ### Unzip2 -> Unzip9 Unzip accepts an array of grouped elements and creates an array regrouping the elements to their pre-zip configuration. @@ -1356,6 +1369,18 @@ a, b := lo.Unzip2([]Tuple2[string, int]{{A: "a", B: 1}, {A: "b", B: 2}}) [[play](https://go.dev/play/p/ciHugugvaAW)] +### UnzipBy2 -> UnzipBy9 + +UnzipBy2 iterates over a collection and creates an array regrouping the elements to their pre-zip configuration. + +```go +a, b := lo.UnzipBy2([]string{"hello", "john", "doe"}, func(str string) (string, int) { + return str, len(str) +}) +// []string{"hello", "john", "doe"} +// []int{5, 4, 3} +``` + ### ChannelDispatcher Distributes messages from input channels into N child channels. Close events are propagated to children. @@ -1924,6 +1949,9 @@ min := lo.Min([]int{1, 2, 3}) min := lo.Min([]int{}) // 0 + +min := lo.Min([]time.Duration{time.Second, time.Hour}) +// 1s ``` ### MinBy @@ -1958,6 +1986,9 @@ max := lo.Max([]int{1, 2, 3}) max := lo.Max([]int{}) // 0 + +max := lo.Max([]time.Duration{time.Second, time.Hour}) +// 1h ``` ### MaxBy @@ -2712,7 +2743,7 @@ lo.Must0(ok, "'%s' must always contain '%s'", myString, requiredChar) list := []int{0, 1, 2} item := 5 -lo.Must0(lo.Contains[int](list, item), "'%s' must always contain '%s'", list, item) +lo.Must0(lo.Contains(list, item), "'%s' must always contain '%s'", list, item) ... ``` @@ -2949,7 +2980,7 @@ make watch-test Give a ⭐️ if this project helped you! -[![support us](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/samber) +[![GitHub Sponsors](https://img.shields.io/github/sponsors/samber?style=for-the-badge)](https://github.com/sponsors/samber) ## 📝 License diff --git a/tuples.go b/tuples.go index cdddf6af..d038230a 100644 --- a/tuples.go +++ b/tuples.go @@ -328,6 +328,178 @@ func Zip9[A any, B any, C any, D any, E any, F any, G any, H any, I any](a []A, return result } +// ZipBy2 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy2[A any, B any, Out any](a []A, b []B, iteratee func(a A, b B) Out) []Out { + size := Max([]int{len(a), len(b)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + + result = append(result, iteratee(_a, _b)) + } + + return result +} + +// ZipBy3 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy3[A any, B any, C any, Out any](a []A, b []B, c []C, iteratee func(a A, b B, c C) Out) []Out { + size := Max([]int{len(a), len(b), len(c)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + + result = append(result, iteratee(_a, _b, _c)) + } + + return result +} + +// ZipBy4 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy4[A any, B any, C any, D any, Out any](a []A, b []B, c []C, d []D, iteratee func(a A, b B, c C, d D) Out) []Out { + size := Max([]int{len(a), len(b), len(c), len(d)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + _d, _ := Nth(d, index) + + result = append(result, iteratee(_a, _b, _c, _d)) + } + + return result +} + +// ZipBy5 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy5[A any, B any, C any, D any, E any, Out any](a []A, b []B, c []C, d []D, e []E, iteratee func(a A, b B, c C, d D, e E) Out) []Out { + size := Max([]int{len(a), len(b), len(c), len(d), len(e)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + _d, _ := Nth(d, index) + _e, _ := Nth(e, index) + + result = append(result, iteratee(_a, _b, _c, _d, _e)) + } + + return result +} + +// ZipBy6 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy6[A any, B any, C any, D any, E any, F any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, iteratee func(a A, b B, c C, d D, e E, f F) Out) []Out { + size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + _d, _ := Nth(d, index) + _e, _ := Nth(e, index) + _f, _ := Nth(f, index) + + result = append(result, iteratee(_a, _b, _c, _d, _e, _f)) + } + + return result +} + +// ZipBy7 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy7[A any, B any, C any, D any, E any, F any, G any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, iteratee func(a A, b B, c C, d D, e E, f F, g G) Out) []Out { + size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + _d, _ := Nth(d, index) + _e, _ := Nth(e, index) + _f, _ := Nth(f, index) + _g, _ := Nth(g, index) + + result = append(result, iteratee(_a, _b, _c, _d, _e, _f, _g)) + } + + return result +} + +// ZipBy8 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy8[A any, B any, C any, D any, E any, F any, G any, H any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out { + size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + _d, _ := Nth(d, index) + _e, _ := Nth(e, index) + _f, _ := Nth(f, index) + _g, _ := Nth(g, index) + _h, _ := Nth(h, index) + + result = append(result, iteratee(_a, _b, _c, _d, _e, _f, _g, _h)) + } + + return result +} + +// ZipBy9 creates a slice of transformed elements, the first of which contains the first elements +// of the given arrays, the second of which contains the second elements of the given arrays, and so on. +// When collections have different size, the Tuple attributes are filled with zero value. +func ZipBy9[A any, B any, C any, D any, E any, F any, G any, H any, I any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out { + size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i)}) + + result := make([]Out, 0, size) + + for index := 0; index < size; index++ { + _a, _ := Nth(a, index) + _b, _ := Nth(b, index) + _c, _ := Nth(c, index) + _d, _ := Nth(d, index) + _e, _ := Nth(e, index) + _f, _ := Nth(f, index) + _g, _ := Nth(g, index) + _h, _ := Nth(h, index) + _i, _ := Nth(i, index) + + result = append(result, iteratee(_a, _b, _c, _d, _e, _f, _g, _h, _i)) + } + + return result +} + // Unzip2 accepts an array of grouped elements and creates an array regrouping the elements // to their pre-zip configuration. // Play: https://go.dev/play/p/ciHugugvaAW @@ -511,3 +683,187 @@ func Unzip9[A any, B any, C any, D any, E any, F any, G any, H any, I any](tuple return r1, r2, r3, r4, r5, r6, r7, r8, r9 } + +// UnzipBy2 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy2[In any, A any, B any](items []In, iteratee func(In) (a A, b B)) ([]A, []B) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + + for _, item := range items { + a, b := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + } + + return r1, r2 +} + +// UnzipBy3 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy3[In any, A any, B any, C any](items []In, iteratee func(In) (a A, b B, c C)) ([]A, []B, []C) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + + for _, item := range items { + a, b, c := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + } + + return r1, r2, r3 +} + +// UnzipBy4 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy4[In any, A any, B any, C any, D any](items []In, iteratee func(In) (a A, b B, c C, d D)) ([]A, []B, []C, []D) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + r4 := make([]D, 0, size) + + for _, item := range items { + a, b, c, d := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + r4 = append(r4, d) + } + + return r1, r2, r3, r4 +} + +// UnzipBy5 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy5[In any, A any, B any, C any, D any, E any](items []In, iteratee func(In) (a A, b B, c C, d D, e E)) ([]A, []B, []C, []D, []E) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + r4 := make([]D, 0, size) + r5 := make([]E, 0, size) + + for _, item := range items { + a, b, c, d, e := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + r4 = append(r4, d) + r5 = append(r5, e) + } + + return r1, r2, r3, r4, r5 +} + +// UnzipBy6 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy6[In any, A any, B any, C any, D any, E any, F any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F)) ([]A, []B, []C, []D, []E, []F) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + r4 := make([]D, 0, size) + r5 := make([]E, 0, size) + r6 := make([]F, 0, size) + + for _, item := range items { + a, b, c, d, e, f := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + r4 = append(r4, d) + r5 = append(r5, e) + r6 = append(r6, f) + } + + return r1, r2, r3, r4, r5, r6 +} + +// UnzipBy7 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy7[In any, A any, B any, C any, D any, E any, F any, G any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G)) ([]A, []B, []C, []D, []E, []F, []G) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + r4 := make([]D, 0, size) + r5 := make([]E, 0, size) + r6 := make([]F, 0, size) + r7 := make([]G, 0, size) + + for _, item := range items { + a, b, c, d, e, f, g := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + r4 = append(r4, d) + r5 = append(r5, e) + r6 = append(r6, f) + r7 = append(r7, g) + } + + return r1, r2, r3, r4, r5, r6, r7 +} + +// UnzipBy8 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy8[In any, A any, B any, C any, D any, E any, F any, G any, H any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H)) ([]A, []B, []C, []D, []E, []F, []G, []H) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + r4 := make([]D, 0, size) + r5 := make([]E, 0, size) + r6 := make([]F, 0, size) + r7 := make([]G, 0, size) + r8 := make([]H, 0, size) + + for _, item := range items { + a, b, c, d, e, f, g, h := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + r4 = append(r4, d) + r5 = append(r5, e) + r6 = append(r6, f) + r7 = append(r7, g) + r8 = append(r8, h) + } + + return r1, r2, r3, r4, r5, r6, r7, r8 +} + +// UnzipBy9 iterates over a collection and creates an array regrouping the elements +// to their pre-zip configuration. +func UnzipBy9[In any, A any, B any, C any, D any, E any, F any, G any, H any, I any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H, i I)) ([]A, []B, []C, []D, []E, []F, []G, []H, []I) { + size := len(items) + r1 := make([]A, 0, size) + r2 := make([]B, 0, size) + r3 := make([]C, 0, size) + r4 := make([]D, 0, size) + r5 := make([]E, 0, size) + r6 := make([]F, 0, size) + r7 := make([]G, 0, size) + r8 := make([]H, 0, size) + r9 := make([]I, 0, size) + + for _, item := range items { + a, b, c, d, e, f, g, h, i := iteratee(item) + r1 = append(r1, a) + r2 = append(r2, b) + r3 = append(r3, c) + r4 = append(r4, d) + r5 = append(r5, e) + r6 = append(r6, f) + r7 = append(r7, g) + r8 = append(r8, h) + r9 = append(r9, i) + } + + return r1, r2, r3, r4, r5, r6, r7, r8, r9 +} diff --git a/tuples_test.go b/tuples_test.go index b5aac617..fccf88cf 100644 --- a/tuples_test.go +++ b/tuples_test.go @@ -213,7 +213,8 @@ func TestZip(t *testing.T) { r2 := Zip3( []string{"a", "b", "c"}, - []int{1, 2, 3}, []int{4, 5, 6}, + []int{1, 2, 3}, + []int{4, 5, 6}, ) r3 := Zip4( @@ -342,6 +343,171 @@ func TestZip(t *testing.T) { }) } +func TestZipBy(t *testing.T) { + t.Parallel() + is := assert.New(t) + + r1 := ZipBy2( + []string{"a", "b"}, + []int{1, 2}, + func(a string, b int) Tuple2[string, int] { + return T2(a, b) + }, + ) + + r2 := ZipBy3( + []string{"a", "b", "c"}, + []int{1, 2, 3}, + []int{4, 5, 6}, + func(a string, b int, c int) Tuple3[string, int, int] { + return T3(a, b, c) + }, + ) + + r3 := ZipBy4( + []string{"a", "b", "c", "d"}, + []int{1, 2, 3, 4}, + []int{5, 6, 7, 8}, + []bool{true, true, true, true}, + func(a string, b int, c int, d bool) Tuple4[string, int, int, bool] { + return T4(a, b, c, d) + }, + ) + + r4 := ZipBy5( + []string{"a", "b", "c", "d", "e"}, + []int{1, 2, 3, 4, 5}, + []int{6, 7, 8, 9, 10}, + []bool{true, true, true, true, true}, + []float32{0.1, 0.2, 0.3, 0.4, 0.5}, + func(a string, b int, c int, d bool, e float32) Tuple5[string, int, int, bool, float32] { + return T5(a, b, c, d, e) + }, + ) + + r5 := ZipBy6( + []string{"a", "b", "c", "d", "e", "f"}, + []int{1, 2, 3, 4, 5, 6}, + []int{7, 8, 9, 10, 11, 12}, + []bool{true, true, true, true, true, true}, + []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6}, + []float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06}, + func(a string, b int, c int, d bool, e float32, f float64) Tuple6[string, int, int, bool, float32, float64] { + return T6(a, b, c, d, e, f) + }, + ) + + r6 := ZipBy7( + []string{"a", "b", "c", "d", "e", "f", "g"}, + []int{1, 2, 3, 4, 5, 6, 7}, + []int{8, 9, 10, 11, 12, 13, 14}, + []bool{true, true, true, true, true, true, true}, + []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}, + []float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07}, + []int8{1, 2, 3, 4, 5, 6, 7}, + func(a string, b int, c int, d bool, e float32, f float64, g int8) Tuple7[string, int, int, bool, float32, float64, int8] { + return T7(a, b, c, d, e, f, g) + }, + ) + + r7 := ZipBy8( + []string{"a", "b", "c", "d", "e", "f", "g", "h"}, + []int{1, 2, 3, 4, 5, 6, 7, 8}, + []int{9, 10, 11, 12, 13, 14, 15, 16}, + []bool{true, true, true, true, true, true, true, true}, + []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, + []float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08}, + []int8{1, 2, 3, 4, 5, 6, 7, 8}, + []int16{1, 2, 3, 4, 5, 6, 7, 8}, + func(a string, b int, c int, d bool, e float32, f float64, g int8, h int16) Tuple8[string, int, int, bool, float32, float64, int8, int16] { + return T8(a, b, c, d, e, f, g, h) + }, + ) + + r8 := ZipBy9( + []string{"a", "b", "c", "d", "e", "f", "g", "h", "i"}, + []int{1, 2, 3, 4, 5, 6, 7, 8, 9}, + []int{10, 11, 12, 13, 14, 15, 16, 17, 18}, + []bool{true, true, true, true, true, true, true, true, true}, + []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}, + []float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09}, + []int8{1, 2, 3, 4, 5, 6, 7, 8, 9}, + []int16{1, 2, 3, 4, 5, 6, 7, 8, 9}, + []int32{1, 2, 3, 4, 5, 6, 7, 8, 9}, + func(a string, b int, c int, d bool, e float32, f float64, g int8, h int16, i int32) Tuple9[string, int, int, bool, float32, float64, int8, int16, int32] { + return T9(a, b, c, d, e, f, g, h, i) + }, + ) + + is.Equal(r1, []Tuple2[string, int]{ + {A: "a", B: 1}, + {A: "b", B: 2}, + }) + + is.Equal(r2, []Tuple3[string, int, int]{ + {A: "a", B: 1, C: 4}, + {A: "b", B: 2, C: 5}, + {A: "c", B: 3, C: 6}, + }) + + is.Equal(r3, []Tuple4[string, int, int, bool]{ + {A: "a", B: 1, C: 5, D: true}, + {A: "b", B: 2, C: 6, D: true}, + {A: "c", B: 3, C: 7, D: true}, + {A: "d", B: 4, C: 8, D: true}, + }) + + is.Equal(r4, []Tuple5[string, int, int, bool, float32]{ + {A: "a", B: 1, C: 6, D: true, E: 0.1}, + {A: "b", B: 2, C: 7, D: true, E: 0.2}, + {A: "c", B: 3, C: 8, D: true, E: 0.3}, + {A: "d", B: 4, C: 9, D: true, E: 0.4}, + {A: "e", B: 5, C: 10, D: true, E: 0.5}, + }) + + is.Equal(r5, []Tuple6[string, int, int, bool, float32, float64]{ + {A: "a", B: 1, C: 7, D: true, E: 0.1, F: 0.01}, + {A: "b", B: 2, C: 8, D: true, E: 0.2, F: 0.02}, + {A: "c", B: 3, C: 9, D: true, E: 0.3, F: 0.03}, + {A: "d", B: 4, C: 10, D: true, E: 0.4, F: 0.04}, + {A: "e", B: 5, C: 11, D: true, E: 0.5, F: 0.05}, + {A: "f", B: 6, C: 12, D: true, E: 0.6, F: 0.06}, + }) + + is.Equal(r6, []Tuple7[string, int, int, bool, float32, float64, int8]{ + {A: "a", B: 1, C: 8, D: true, E: 0.1, F: 0.01, G: 1}, + {A: "b", B: 2, C: 9, D: true, E: 0.2, F: 0.02, G: 2}, + {A: "c", B: 3, C: 10, D: true, E: 0.3, F: 0.03, G: 3}, + {A: "d", B: 4, C: 11, D: true, E: 0.4, F: 0.04, G: 4}, + {A: "e", B: 5, C: 12, D: true, E: 0.5, F: 0.05, G: 5}, + {A: "f", B: 6, C: 13, D: true, E: 0.6, F: 0.06, G: 6}, + {A: "g", B: 7, C: 14, D: true, E: 0.7, F: 0.07, G: 7}, + }) + + is.Equal(r7, []Tuple8[string, int, int, bool, float32, float64, int8, int16]{ + {A: "a", B: 1, C: 9, D: true, E: 0.1, F: 0.01, G: 1, H: 1}, + {A: "b", B: 2, C: 10, D: true, E: 0.2, F: 0.02, G: 2, H: 2}, + {A: "c", B: 3, C: 11, D: true, E: 0.3, F: 0.03, G: 3, H: 3}, + {A: "d", B: 4, C: 12, D: true, E: 0.4, F: 0.04, G: 4, H: 4}, + {A: "e", B: 5, C: 13, D: true, E: 0.5, F: 0.05, G: 5, H: 5}, + {A: "f", B: 6, C: 14, D: true, E: 0.6, F: 0.06, G: 6, H: 6}, + {A: "g", B: 7, C: 15, D: true, E: 0.7, F: 0.07, G: 7, H: 7}, + {A: "h", B: 8, C: 16, D: true, E: 0.8, F: 0.08, G: 8, H: 8}, + }) + + is.Equal(r8, []Tuple9[string, int, int, bool, float32, float64, int8, int16, int32]{ + {A: "a", B: 1, C: 10, D: true, E: 0.1, F: 0.01, G: 1, H: 1, I: 1}, + {A: "b", B: 2, C: 11, D: true, E: 0.2, F: 0.02, G: 2, H: 2, I: 2}, + {A: "c", B: 3, C: 12, D: true, E: 0.3, F: 0.03, G: 3, H: 3, I: 3}, + {A: "d", B: 4, C: 13, D: true, E: 0.4, F: 0.04, G: 4, H: 4, I: 4}, + {A: "e", B: 5, C: 14, D: true, E: 0.5, F: 0.05, G: 5, H: 5, I: 5}, + {A: "f", B: 6, C: 15, D: true, E: 0.6, F: 0.06, G: 6, H: 6, I: 6}, + {A: "g", B: 7, C: 16, D: true, E: 0.7, F: 0.07, G: 7, H: 7, I: 7}, + {A: "h", B: 8, C: 17, D: true, E: 0.8, F: 0.08, G: 8, H: 8, I: 8}, + {A: "i", B: 9, C: 18, D: true, E: 0.9, F: 0.09, G: 9, H: 9, I: 9}, + }) +} + func TestUnzip(t *testing.T) { t.Parallel() is := assert.New(t) @@ -351,3 +517,15 @@ func TestUnzip(t *testing.T) { is.Equal(r1, []string{"a", "b"}) is.Equal(r2, []int{1, 2}) } + +func TestUnzipBy(t *testing.T) { + t.Parallel() + is := assert.New(t) + + r1, r2 := UnzipBy2([]Tuple2[string, int]{{A: "a", B: 1}, {A: "b", B: 2}}, func(i Tuple2[string, int]) (a string, b int) { + return i.A + i.A, i.B + i.B + }) + + is.Equal(r1, []string{"aa", "bb"}) + is.Equal(r2, []int{2, 4}) +}