Skip to content

Commit 7c8c1f1

Browse files
author
Tom Godkin
committed
Merge branch 'feature/filter-map'
2 parents eabd99b + 2e6d4c3 commit 7c8c1f1

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

iter/filter.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,30 @@ func Exclude[T any](iter Iterator[T], fun func(T) bool) *FilterIter[T] {
3636
inverse := func(t T) bool { return !fun(t) }
3737
return &FilterIter[T]{iter, inverse}
3838
}
39+
40+
type FilterMapIter[T any, U any] struct {
41+
itr Iterator[T]
42+
fn func(T) option.Option[U]
43+
}
44+
45+
func (flt *FilterMapIter[T, U]) Next() option.Option[U] {
46+
for {
47+
val, ok := flt.itr.Next().Value()
48+
if !ok {
49+
return option.None[U]()
50+
}
51+
result := flt.fn(val)
52+
if result.IsSome() {
53+
return result
54+
}
55+
}
56+
}
57+
58+
var _ Iterator[struct{}] = new(FilterMapIter[struct{}, struct{}])
59+
60+
// Accepts an underlying iterator as data source and a filtering + mapping function
61+
// it allows the user to filter elements by returning a None variant and to transform
62+
// elements by returning a Some variant.
63+
func FilterMap[T any, U any](itr Iterator[T], fun func(T) option.Option[U]) Iterator[U] {
64+
return &FilterMapIter[T, U]{itr, fun}
65+
}

iter/filter_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/BooleanCat/go-functional/internal/assert"
88
"github.com/BooleanCat/go-functional/iter"
99
"github.com/BooleanCat/go-functional/iter/filters"
10+
"github.com/BooleanCat/go-functional/option"
1011
)
1112

1213
func ExampleFilter() {
@@ -21,6 +22,24 @@ func ExampleFilter() {
2122
// None
2223
}
2324

25+
func ExampleFilterMap() {
26+
selectAndTripleOdds := func(x int) option.Option[int] {
27+
if x%2 == 0 {
28+
return option.None[int]()
29+
}
30+
return option.Some(x * 3)
31+
}
32+
33+
triples := iter.FilterMap[int](
34+
iter.Take[int](iter.Count(), 6),
35+
selectAndTripleOdds,
36+
)
37+
38+
fmt.Println(iter.Collect(triples))
39+
40+
// Output: [3 9 15]
41+
}
42+
2443
func ExampleExclude() {
2544
filtered := iter.Exclude[int](iter.Lift([]int{0, 1, 0, 2}), filters.IsZero[int])
2645
fmt.Println(filtered.Next())
@@ -52,3 +71,38 @@ func TestExclude(t *testing.T) {
5271
assert.Equal(t, evens.Next().Unwrap(), 1)
5372
assert.Equal(t, evens.Next().Unwrap(), 3)
5473
}
74+
75+
func TestFilterMap(t *testing.T) {
76+
selectEvenAndDouble := func(x int) option.Option[int] {
77+
if x%2 > 0 {
78+
return option.None[int]()
79+
}
80+
81+
return option.Some(x * 2)
82+
}
83+
84+
fltMap := iter.FilterMap[int](
85+
iter.Lift([]int{1, 2, 3, 4, 5, 6}),
86+
selectEvenAndDouble,
87+
)
88+
result := iter.Collect(fltMap)
89+
90+
assert.SliceEqual(t, result, []int{4, 8, 12})
91+
}
92+
93+
func TestFilterMapEmpty(t *testing.T) {
94+
selectEvenAndDouble := func(x int) option.Option[int] {
95+
if x%2 > 0 {
96+
return option.None[int]()
97+
}
98+
99+
return option.Some(x * 2)
100+
}
101+
102+
fltMapEmpty := iter.FilterMap[int](
103+
iter.Exhausted[int](),
104+
selectEvenAndDouble,
105+
)
106+
107+
assert.Empty(t, iter.Collect(fltMapEmpty))
108+
}

0 commit comments

Comments
 (0)