Skip to content

Commit e2bf478

Browse files
committed
feat: add Zip and ZipWith helpers with docs and tests
1 parent bb5c82d commit e2bf478

File tree

7 files changed

+505
-3
lines changed

7 files changed

+505
-3
lines changed

README.md

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ go get github.com/goforj/collection
142142
| **Serialization** | [ToJSON](#tojson) [ToPrettyJSON](#toprettyjson) |
143143
| **Set Operations** | [Difference](#difference) [Intersect](#intersect) [SymmetricDifference](#symmetricdifference) [Union](#union) [Unique](#unique) [UniqueBy](#uniqueby) |
144144
| **Slicing** | [Chunk](#chunk) [Filter](#filter) [Partition](#partition) [Pop](#pop) [PopN](#popn) [Skip](#skip) [SkipLast](#skiplast) [Take](#take) [TakeLast](#takelast) [TakeUntil](#takeuntil) [TakeUntilFn](#takeuntilfn) |
145-
| **Transformation** | [Append](#append) [Concat](#concat) [Each](#each) [Map](#map) [MapTo](#mapto) [Merge](#merge) [Multiply](#multiply) [Pipe](#pipe) [Pluck](#pluck) [Prepend](#prepend) [Push](#push) [Tap](#tap) [Times](#times) [Transform](#transform) |
145+
| **Transformation** | [Append](#append) [Concat](#concat) [Each](#each) [Map](#map) [MapTo](#mapto) [Merge](#merge) [Multiply](#multiply) [Pipe](#pipe) [Pluck](#pluck) [Prepend](#prepend) [Push](#push) [Tap](#tap) [Times](#times) [Transform](#transform) [Zip](#zip) [ZipWith](#zipwith) |
146146

147147

148148
## Access
@@ -3936,4 +3936,127 @@ collection.Dump(c3.Items())
39363936
// 1 => {ID:2 Name:"BOB"} #collection.User
39373937
// ]
39383938
```
3939+
3940+
### <a id="zip"></a>Zip · immutable
3941+
3942+
Zip combines two collections element-wise into a collection of tuples.
3943+
The resulting length is the smaller of the two inputs.
3944+
3945+
_Example: integers and strings_
3946+
3947+
```go
3948+
nums := collection.New([]int{1, 2, 3})
3949+
words := collection.New([]string{"one", "two"})
3950+
3951+
out := collection.Zip(nums, words)
3952+
collection.Dump(out.Items())
3953+
// #[]collection.Tuple[int,string] [
3954+
// 0 => #collection.Tuple[int,string] {
3955+
// +First => 1 #int
3956+
// +Second => "one" #string
3957+
// }
3958+
// 1 => #collection.Tuple[int,string] {
3959+
// +First => 2 #int
3960+
// +Second => "two" #string
3961+
// }
3962+
// ]
3963+
```
3964+
3965+
_Example: structs_
3966+
3967+
```go
3968+
type User struct {
3969+
ID int
3970+
Name string
3971+
}
3972+
3973+
users := collection.New([]User{
3974+
{ID: 1, Name: "Alice"},
3975+
{ID: 2, Name: "Bob"},
3976+
})
3977+
3978+
roles := collection.New([]string{"admin", "user", "extra"})
3979+
3980+
out2 := collection.Zip(users, roles)
3981+
collection.Dump(out2.Items())
3982+
// #[]collection.Tuple[main.User,string] [
3983+
// 0 => #collection.Tuple[main.User,string] {
3984+
// +First => #main.User {
3985+
// +ID => 1 #int
3986+
// +Name => "Alice" #string
3987+
// }
3988+
// +Second => "admin" #string
3989+
// }
3990+
// 1 => #collection.Tuple[main.User,string] {
3991+
// +First => #main.User {
3992+
// +ID => 2 #int
3993+
// +Name => "Bob" #string
3994+
// }
3995+
// +Second => "user" #string
3996+
// }
3997+
// ]
3998+
```
3999+
4000+
### <a id="zipwith"></a>ZipWith · immutable
4001+
4002+
ZipWith combines two collections element-wise using combiner fn.
4003+
The resulting length is the smaller of the two inputs.
4004+
4005+
_Example: sum ints_
4006+
4007+
```go
4008+
a := collection.New([]int{1, 2, 3})
4009+
b := collection.New([]int{10, 20})
4010+
4011+
out := collection.ZipWith(a, b, func(x, y int) int {
4012+
return x + y
4013+
})
4014+
4015+
collection.Dump(out.Items())
4016+
// #[]int [
4017+
// 0 => 11 #int
4018+
// 1 => 22 #int
4019+
// ]
4020+
```
4021+
4022+
_Example: format strings_
4023+
4024+
```go
4025+
names := collection.New([]string{"alice", "bob"})
4026+
roles := collection.New([]string{"admin", "user", "extra"})
4027+
4028+
out2 := collection.ZipWith(names, roles, func(name, role string) string {
4029+
return name + ":" + role
4030+
})
4031+
4032+
collection.Dump(out2.Items())
4033+
// #[]string [
4034+
// 0 => "alice:admin" #string
4035+
// 1 => "bob:user" #string
4036+
// ]
4037+
```
4038+
4039+
_Example: structs_
4040+
4041+
```go
4042+
type User struct {
4043+
Name string
4044+
}
4045+
4046+
type Role struct {
4047+
Title string
4048+
}
4049+
4050+
users := collection.New([]User{{Name: "Alice"}, {Name: "Bob"}})
4051+
roles2 := collection.New([]Role{{Title: "admin"}})
4052+
4053+
out3 := collection.ZipWith(users, roles2, func(u User, r Role) string {
4054+
return u.Name + " -> " + r.Title
4055+
})
4056+
4057+
collection.Dump(out3.Items())
4058+
// #[]string [
4059+
// 0 => "Alice -> admin" #string
4060+
// ]
4061+
```
39394062
<!-- api:embed:end -->

examples/partition/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
package main
55

66
import (
7-
"strings"
8-
97
"github.com/goforj/collection"
8+
"strings"
109
)
1110

1211
func main() {

examples/zip/main.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
package main
5+
6+
import "github.com/goforj/collection"
7+
8+
func main() {
9+
// Zip combines two collections element-wise into a collection of tuples.
10+
// The resulting length is the smaller of the two inputs.
11+
12+
// Example: integers and strings
13+
nums := collection.New([]int{1, 2, 3})
14+
words := collection.New([]string{"one", "two"})
15+
16+
out := collection.Zip(nums, words)
17+
collection.Dump(out.Items())
18+
// #[]collection.Tuple[int,string] [
19+
// 0 => #collection.Tuple[int,string] {
20+
// +First => 1 #int
21+
// +Second => "one" #string
22+
// }
23+
// 1 => #collection.Tuple[int,string] {
24+
// +First => 2 #int
25+
// +Second => "two" #string
26+
// }
27+
// ]
28+
29+
// Example: structs
30+
type User struct {
31+
ID int
32+
Name string
33+
}
34+
35+
users := collection.New([]User{
36+
{ID: 1, Name: "Alice"},
37+
{ID: 2, Name: "Bob"},
38+
})
39+
40+
roles := collection.New([]string{"admin", "user", "extra"})
41+
42+
out2 := collection.Zip(users, roles)
43+
collection.Dump(out2.Items())
44+
// #[]collection.Tuple[main.User,string] [
45+
// 0 => #collection.Tuple[main.User,string] {
46+
// +First => #main.User {
47+
// +ID => 1 #int
48+
// +Name => "Alice" #string
49+
// }
50+
// +Second => "admin" #string
51+
// }
52+
// 1 => #collection.Tuple[main.User,string] {
53+
// +First => #main.User {
54+
// +ID => 2 #int
55+
// +Name => "Bob" #string
56+
// }
57+
// +Second => "user" #string
58+
// }
59+
// ]
60+
}

examples/zipwith/main.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
package main
5+
6+
import "github.com/goforj/collection"
7+
8+
func main() {
9+
// ZipWith combines two collections element-wise using combiner fn.
10+
// The resulting length is the smaller of the two inputs.
11+
12+
// Example: sum ints
13+
a := collection.New([]int{1, 2, 3})
14+
b := collection.New([]int{10, 20})
15+
16+
out := collection.ZipWith(a, b, func(x, y int) int {
17+
return x + y
18+
})
19+
20+
collection.Dump(out.Items())
21+
// #[]int [
22+
// 0 => 11 #int
23+
// 1 => 22 #int
24+
// ]
25+
26+
// Example: format strings
27+
names := collection.New([]string{"alice", "bob"})
28+
roles := collection.New([]string{"admin", "user", "extra"})
29+
30+
out2 := collection.ZipWith(names, roles, func(name, role string) string {
31+
return name + ":" + role
32+
})
33+
34+
collection.Dump(out2.Items())
35+
// #[]string [
36+
// 0 => "alice:admin" #string
37+
// 1 => "bob:user" #string
38+
// ]
39+
40+
// Example: structs
41+
type User struct {
42+
Name string
43+
}
44+
45+
type Role struct {
46+
Title string
47+
}
48+
49+
users := collection.New([]User{{Name: "Alice"}, {Name: "Bob"}})
50+
roles2 := collection.New([]Role{{Title: "admin"}})
51+
52+
out3 := collection.ZipWith(users, roles2, func(u User, r Role) string {
53+
return u.Name + " -> " + r.Title
54+
})
55+
56+
collection.Dump(out3.Items())
57+
// #[]string [
58+
// 0 => "Alice -> admin" #string
59+
// ]
60+
}

tuple.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package collection
2+
3+
// Tuple is a generic ordered pair of values, used by helpers like Zip.
4+
type Tuple[A any, B any] struct {
5+
First A
6+
Second B
7+
}

0 commit comments

Comments
 (0)