Skip to content

Commit b35a87e

Browse files
rjNemoclaude
andauthored
feat: add TakeWhile and DropWhile functions (#42)
- Add TakeWhile: returns elements while predicate is true - Add DropWhile: drops elements while predicate is true - Comprehensive tests including edge cases - Benchmarks included Resolves Issue 14 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3617c2d commit b35a87e

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

dropwhile.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package underscore
2+
3+
// DropWhile drops elements from the beginning of the slice while the predicate returns true.
4+
// It returns the remaining elements starting from the first element where the predicate returns false.
5+
func DropWhile[T any](values []T, predicate func(T) bool) []T {
6+
for i, v := range values {
7+
if !predicate(v) {
8+
res := make([]T, len(values)-i)
9+
copy(res, values[i:])
10+
return res
11+
}
12+
}
13+
// All elements satisfy predicate, return empty slice
14+
return []T{}
15+
}

dropwhile_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package underscore_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
u "github.com/rjNemo/underscore"
9+
)
10+
11+
func TestDropWhile(t *testing.T) {
12+
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
13+
result := u.DropWhile(nums, func(n int) bool { return n < 5 })
14+
assert.Equal(t, []int{5, 6, 7, 8, 9}, result)
15+
}
16+
17+
func TestDropWhileEmpty(t *testing.T) {
18+
result := u.DropWhile([]int{}, func(n int) bool { return n < 5 })
19+
assert.Equal(t, []int{}, result)
20+
}
21+
22+
func TestDropWhileNoneMatch(t *testing.T) {
23+
nums := []int{5, 6, 7, 8, 9}
24+
result := u.DropWhile(nums, func(n int) bool { return n < 5 })
25+
assert.Equal(t, []int{5, 6, 7, 8, 9}, result)
26+
}
27+
28+
func TestDropWhileAllMatch(t *testing.T) {
29+
nums := []int{1, 2, 3, 4}
30+
result := u.DropWhile(nums, func(n int) bool { return n < 10 })
31+
assert.Equal(t, []int{}, result)
32+
}
33+
34+
func TestDropWhileSingleElement(t *testing.T) {
35+
result := u.DropWhile([]int{5}, func(n int) bool { return n < 10 })
36+
assert.Equal(t, []int{}, result)
37+
}
38+
39+
func TestDropWhileStrings(t *testing.T) {
40+
words := []string{"apple", "banana", "cherry", "date"}
41+
result := u.DropWhile(words, func(s string) bool { return len(s) < 6 })
42+
assert.Equal(t, []string{"banana", "cherry", "date"}, result)
43+
}
44+
45+
func BenchmarkDropWhile(b *testing.B) {
46+
nums := make([]int, 1000)
47+
for i := range nums {
48+
nums[i] = i
49+
}
50+
51+
b.ResetTimer()
52+
for i := 0; i < b.N; i++ {
53+
u.DropWhile(nums, func(n int) bool { return n < 500 })
54+
}
55+
}

takewhile.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package underscore
2+
3+
// TakeWhile returns elements from the beginning of the slice while the predicate returns true.
4+
// It stops at the first element where the predicate returns false.
5+
func TakeWhile[T any](values []T, predicate func(T) bool) []T {
6+
for i, v := range values {
7+
if !predicate(v) {
8+
res := make([]T, i)
9+
copy(res, values[:i])
10+
return res
11+
}
12+
}
13+
// All elements satisfy predicate
14+
res := make([]T, len(values))
15+
copy(res, values)
16+
return res
17+
}

takewhile_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package underscore_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
u "github.com/rjNemo/underscore"
9+
)
10+
11+
func TestTakeWhile(t *testing.T) {
12+
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
13+
result := u.TakeWhile(nums, func(n int) bool { return n < 5 })
14+
assert.Equal(t, []int{1, 2, 3, 4}, result)
15+
}
16+
17+
func TestTakeWhileEmpty(t *testing.T) {
18+
result := u.TakeWhile([]int{}, func(n int) bool { return n < 5 })
19+
assert.Equal(t, []int{}, result)
20+
}
21+
22+
func TestTakeWhileNoneMatch(t *testing.T) {
23+
nums := []int{5, 6, 7, 8, 9}
24+
result := u.TakeWhile(nums, func(n int) bool { return n < 5 })
25+
assert.Equal(t, []int{}, result)
26+
}
27+
28+
func TestTakeWhileAllMatch(t *testing.T) {
29+
nums := []int{1, 2, 3, 4}
30+
result := u.TakeWhile(nums, func(n int) bool { return n < 10 })
31+
assert.Equal(t, []int{1, 2, 3, 4}, result)
32+
}
33+
34+
func TestTakeWhileSingleElement(t *testing.T) {
35+
result := u.TakeWhile([]int{5}, func(n int) bool { return n < 10 })
36+
assert.Equal(t, []int{5}, result)
37+
}
38+
39+
func TestTakeWhileStrings(t *testing.T) {
40+
words := []string{"apple", "banana", "cherry", "date"}
41+
result := u.TakeWhile(words, func(s string) bool { return len(s) < 6 })
42+
assert.Equal(t, []string{"apple"}, result)
43+
}
44+
45+
func BenchmarkTakeWhile(b *testing.B) {
46+
nums := make([]int, 1000)
47+
for i := range nums {
48+
nums[i] = i
49+
}
50+
51+
b.ResetTimer()
52+
for i := 0; i < b.N; i++ {
53+
u.TakeWhile(nums, func(n int) bool { return n < 500 })
54+
}
55+
}

0 commit comments

Comments
 (0)