mirror of
https://github.com/rjNemo/underscore
synced 2026-06-06 02:26:42 +00:00
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>
This commit is contained in:
parent
3617c2de8f
commit
b35a87e50c
4 changed files with 142 additions and 0 deletions
15
dropwhile.go
Normal file
15
dropwhile.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package underscore
|
||||||
|
|
||||||
|
// DropWhile drops elements from the beginning of the slice while the predicate returns true.
|
||||||
|
// It returns the remaining elements starting from the first element where the predicate returns false.
|
||||||
|
func DropWhile[T any](values []T, predicate func(T) bool) []T {
|
||||||
|
for i, v := range values {
|
||||||
|
if !predicate(v) {
|
||||||
|
res := make([]T, len(values)-i)
|
||||||
|
copy(res, values[i:])
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All elements satisfy predicate, return empty slice
|
||||||
|
return []T{}
|
||||||
|
}
|
||||||
55
dropwhile_test.go
Normal file
55
dropwhile_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package underscore_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
u "github.com/rjNemo/underscore"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDropWhile(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||||
|
result := u.DropWhile(nums, func(n int) bool { return n < 5 })
|
||||||
|
assert.Equal(t, []int{5, 6, 7, 8, 9}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDropWhileEmpty(t *testing.T) {
|
||||||
|
result := u.DropWhile([]int{}, func(n int) bool { return n < 5 })
|
||||||
|
assert.Equal(t, []int{}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDropWhileNoneMatch(t *testing.T) {
|
||||||
|
nums := []int{5, 6, 7, 8, 9}
|
||||||
|
result := u.DropWhile(nums, func(n int) bool { return n < 5 })
|
||||||
|
assert.Equal(t, []int{5, 6, 7, 8, 9}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDropWhileAllMatch(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 4}
|
||||||
|
result := u.DropWhile(nums, func(n int) bool { return n < 10 })
|
||||||
|
assert.Equal(t, []int{}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDropWhileSingleElement(t *testing.T) {
|
||||||
|
result := u.DropWhile([]int{5}, func(n int) bool { return n < 10 })
|
||||||
|
assert.Equal(t, []int{}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDropWhileStrings(t *testing.T) {
|
||||||
|
words := []string{"apple", "banana", "cherry", "date"}
|
||||||
|
result := u.DropWhile(words, func(s string) bool { return len(s) < 6 })
|
||||||
|
assert.Equal(t, []string{"banana", "cherry", "date"}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDropWhile(b *testing.B) {
|
||||||
|
nums := make([]int, 1000)
|
||||||
|
for i := range nums {
|
||||||
|
nums[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
u.DropWhile(nums, func(n int) bool { return n < 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
17
takewhile.go
Normal file
17
takewhile.go
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package underscore
|
||||||
|
|
||||||
|
// TakeWhile returns elements from the beginning of the slice while the predicate returns true.
|
||||||
|
// It stops at the first element where the predicate returns false.
|
||||||
|
func TakeWhile[T any](values []T, predicate func(T) bool) []T {
|
||||||
|
for i, v := range values {
|
||||||
|
if !predicate(v) {
|
||||||
|
res := make([]T, i)
|
||||||
|
copy(res, values[:i])
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All elements satisfy predicate
|
||||||
|
res := make([]T, len(values))
|
||||||
|
copy(res, values)
|
||||||
|
return res
|
||||||
|
}
|
||||||
55
takewhile_test.go
Normal file
55
takewhile_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package underscore_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
u "github.com/rjNemo/underscore"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTakeWhile(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||||
|
result := u.TakeWhile(nums, func(n int) bool { return n < 5 })
|
||||||
|
assert.Equal(t, []int{1, 2, 3, 4}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTakeWhileEmpty(t *testing.T) {
|
||||||
|
result := u.TakeWhile([]int{}, func(n int) bool { return n < 5 })
|
||||||
|
assert.Equal(t, []int{}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTakeWhileNoneMatch(t *testing.T) {
|
||||||
|
nums := []int{5, 6, 7, 8, 9}
|
||||||
|
result := u.TakeWhile(nums, func(n int) bool { return n < 5 })
|
||||||
|
assert.Equal(t, []int{}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTakeWhileAllMatch(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 4}
|
||||||
|
result := u.TakeWhile(nums, func(n int) bool { return n < 10 })
|
||||||
|
assert.Equal(t, []int{1, 2, 3, 4}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTakeWhileSingleElement(t *testing.T) {
|
||||||
|
result := u.TakeWhile([]int{5}, func(n int) bool { return n < 10 })
|
||||||
|
assert.Equal(t, []int{5}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTakeWhileStrings(t *testing.T) {
|
||||||
|
words := []string{"apple", "banana", "cherry", "date"}
|
||||||
|
result := u.TakeWhile(words, func(s string) bool { return len(s) < 6 })
|
||||||
|
assert.Equal(t, []string{"apple"}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTakeWhile(b *testing.B) {
|
||||||
|
nums := make([]int, 1000)
|
||||||
|
for i := range nums {
|
||||||
|
nums[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
u.TakeWhile(nums, func(n int) bool { return n < 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue