Skip to content

Commit

Permalink
Introduce a stream.FlatMapSlice function for convenience.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfourny committed Feb 2, 2024
1 parent 866a2ba commit fc870f4
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
38 changes: 30 additions & 8 deletions pkg/stream/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,12 @@ func MapOrDiscard[E, F any](s Stream[E], m OptionalMapper[E, F]) Stream[F] {
}
}

// FlatMapper represents a function that takes an input of type E and returns an output stream of type F.
// It is used to map each element of the input stream to a new stream of elements of type F.
// The FlatMapper function is typically used as a parameter in the FlatMap function.
// StreamMapper represents a function that takes an input of type E and returns an output stream of type F.
// The StreamMapper function is typically used as a parameter of the FlatMap function.
// It must be idempotent, free of side effects, and thread-safe.
type FlatMapper[E, F any] func(from E) (to Stream[F])
type StreamMapper[E, F any] func(from E) (to Stream[F])

// FlatMap applies a FlatMapper function to each element in a stream and returns a new stream containing the mapped elements.
// All mapped streams are flattened into a single stream.
// FlatMap applies a StreamMapper function to each element from the given stream and flattens the returned streams into an output stream.
//
// Example usage:
//
Expand All @@ -70,10 +68,34 @@ type FlatMapper[E, F any] func(from E) (to Stream[F])
// },
// )
// out := stream.DebugString(s) // "<1, 1, 2, 2, 3, 3>"
func FlatMap[E, F any](s Stream[E], fm FlatMapper[E, F]) Stream[F] {
func FlatMap[E, F any](s Stream[E], m StreamMapper[E, F]) Stream[F] {
return func(yield Consumer[F]) bool {
return s(func(e E) bool {
return fm(e)(yield)
return m(e)(yield)
})
}
}

// SliceMapper represents a function that takes an input of type E and returns an output slice of type F.
// The SliceMapper function is typically used as a parameter of the FlatMapSlice function.
// It must be idempotent, free of side effects, and thread-safe.
type SliceMapper[E, F any] func(from E) (to []F)

// FlatMapSlice applies a SliceMapper function to each element from the given stream and flattens the returned slices into an output stream.
//
// Example usage:
//
// s := stream.FlatMapSlice(
// stream.Of(1, 2, 3),
// func(e int) []string { // e -> ["e", "e"]
// return []string{mapper.Sprint(e), mapper.Sprint(e)}
// },
// )
// out := stream.DebugString(s) // "<1, 1, 2, 2, 3, 3>"
func FlatMapSlice[E, F any](s Stream[E], m SliceMapper[E, F]) Stream[F] {
return func(yield Consumer[F]) bool {
return s(func(e E) bool {
return FromSlice(m(e))(yield)
})
}
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/stream/transform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ func TestFlatMap(t *testing.T) {
assert.ElementsMatch(t, got, want)
}

func TestFlatMapSlice(t *testing.T) {
s := FlatMapSlice(Of(1, 2, 3), func(e int) []string {
return []string{fmt.Sprintf("%dA", e), fmt.Sprintf("%dB", e)}
})
got := CollectSlice(s)
want := []string{"1A", "1B", "2A", "2B", "3A", "3B"}
assert.ElementsMatch(t, got, want)
}

func TestSortAsc(t *testing.T) {
s := SortAsc(Of(3, 1, 2))
got := CollectSlice(s)
Expand Down

0 comments on commit fc870f4

Please sign in to comment.