Skip to content

Commit

Permalink
#21 Add TakeWhile Implements
Browse files Browse the repository at this point in the history
  • Loading branch information
meian committed Jan 23, 2022
1 parent fd68efb commit 8f05317
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
49 changes: 49 additions & 0 deletions take.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,52 @@ func (it *takeIterator[T]) MoveNext() bool {
func (it *takeIterator[T]) Current() T {
return it.current
}

type takeWhileIterable[T any] struct {
itb Iterable[T]
whileFunc func(v T) bool
}

type takeWhileIterator[T any] struct {
it Iterator[T]
whileFunc func(v T) bool
done bool
current T
}

// TakeWhile makes Iterable with elements in which whileFunc is true from ahead.
//
// itb := gcf.FromSlice([]{1, 2, 3})
// itb = gcf.TakeWhile(itb, func(v int) bool { return v <= 2 })
//
// If whileFunc is nil, returns original Iterable.
func TakeWhile[T any](itb Iterable[T], whileFunc func(v T) bool) Iterable[T] {
if itb == nil {
return empty[T]()
}
if whileFunc == nil {
return itb
}
return &takeWhileIterable[T]{itb, whileFunc}
}

func (itb *takeWhileIterable[T]) Iterator() Iterator[T] {
return &takeWhileIterator[T]{itb.itb.Iterator(), itb.whileFunc, false, zero[T]()}
}

func (it *takeWhileIterator[T]) MoveNext() bool {
if it.done {
return false
}
if it.it.MoveNext() && it.whileFunc(it.it.Current()) {
it.current = it.it.Current()
return true
}
it.done = true
it.current = zero[T]()
return false
}

func (it *takeWhileIterator[T]) Current() T {
return it.current
}
81 changes: 81 additions & 0 deletions take_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,84 @@ func ExampleTake() {
// Output:
// [1 2 3]
}

func TestTakeWhile(t *testing.T) {
type args struct {
itb gcf.Iterable[int]
whileFunc func(v int) bool
}
tests := []struct {
name string
args args
want []int
}{
{
name: "all true",
args: args{
itb: gcf.FromSlice([]int{1, 2, 3}),
whileFunc: func(v int) bool { return true },
},
want: []int{1, 2, 3},
},
{
name: "all false",
args: args{
itb: gcf.FromSlice([]int{1, 2, 3}),
whileFunc: func(v int) bool { return false },
},
want: []int{},
},
{
name: "partial true from ahead",
args: args{
itb: gcf.FromSlice([]int{1, 2, 3}),
whileFunc: func(v int) bool { return v <= 2 },
},
want: []int{1, 2},
},
{
name: "partial true not from ahead",
args: args{
itb: gcf.FromSlice([]int{1, 2, 3}),
whileFunc: func(v int) bool { return v >= 2 },
},
want: []int{},
},
{
name: "nil func",
args: args{
itb: gcf.FromSlice([]int{1, 2, 3}),
whileFunc: nil,
},
want: []int{1, 2, 3},
},
{
name: "nil Iterable",
args: args{
itb: nil,
whileFunc: func(v int) bool { return true },
},
want: []int{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
itb := gcf.TakeWhile(tt.args.itb, tt.args.whileFunc)
s := gcf.ToSlice(itb)
assert.Equal(t, tt.want, s)
})
}

itb := gcf.FromSlice([]int{1, 2, 3})
itb = gcf.TakeWhile(itb, func(v int) bool { return v < 2 })
testBeforeAndAfter(t, itb)
}

func ExampleTakeWhile() {
itb := gcf.FromSlice([]int{1, 3, 5, 7, 2, 4, 6, 8, 9})
itb = gcf.TakeWhile(itb, func(v int) bool { return v%2 > 0 })
s := gcf.ToSlice(itb)
fmt.Println(s)
// Output:
// [1 3 5 7]
}

0 comments on commit 8f05317

Please sign in to comment.