diff --git a/slicex/README.md b/slicex/README.md index 655575c..12a2e3f 100644 --- a/slicex/README.md +++ b/slicex/README.md @@ -52,4 +52,7 @@ func SymmetricDiff(slices ...[]T) []T // Intersect 计算交集 func Intersect(slices ...[]T) []T + +// Filter 返回符合 f 的元素组成的新切片 +func Filter(s []T, f func(T) bool) []T ``` \ No newline at end of file diff --git a/slicex/filter.go b/slicex/filter.go new file mode 100644 index 0000000..d68e6a0 --- /dev/null +++ b/slicex/filter.go @@ -0,0 +1,13 @@ +package slicex + +// Filter 返回符合 f 的元素组成的新切片 +func Filter[T any](s []T, f func(T) bool) []T { + // var result []T + result := make([]T, 0) // 保证不是 nil + for _, v := range s { + if f(v) { + result = append(result, v) + } + } + return result +} diff --git a/slicex/filter_example_test.go b/slicex/filter_example_test.go new file mode 100644 index 0000000..fe0f319 --- /dev/null +++ b/slicex/filter_example_test.go @@ -0,0 +1,23 @@ +package slicex + +import ( + "fmt" +) + +func ExampleFilter() { + numbers := []int{1, 2, 3, 4, 5} + even := Filter(numbers, func(n int) bool { + return n%2 == 0 + }) + fmt.Println(even) + + words := []string{"go", "java", "c", "python"} + longWords := Filter(words, func(s string) bool { + return len(s) > 2 + }) + fmt.Println(longWords) + + // Output: + // [2 4] + // [java python] +} diff --git a/slicex/filter_test.go b/slicex/filter_test.go new file mode 100644 index 0000000..5380f15 --- /dev/null +++ b/slicex/filter_test.go @@ -0,0 +1,77 @@ +package slicex + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFilter(t *testing.T) { + testCases := []struct { + name string + input []int + filterFn func(int) bool + want []int + }{ + { + name: "filter even numbers", + input: []int{1, 2, 3, 4, 5, 6}, + filterFn: func(i int) bool { return i%2 == 0 }, + want: []int{2, 4, 6}, + }, + { + name: "filter all", + input: []int{1, 2, 3}, + filterFn: func(i int) bool { return true }, + want: []int{1, 2, 3}, + }, + { + name: "filter none", + input: []int{1, 2, 3}, + filterFn: func(i int) bool { return false }, + want: []int{}, + }, + { + name: "empty input", + input: []int{}, + filterFn: func(i int) bool { return i > 0 }, + want: []int{}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := Filter(tc.input, tc.filterFn) + assert.Equal(t, tc.want, got) + }) + } +} + +func TestFilterStrings(t *testing.T) { + testCases := []struct { + name string + input []string + filterFn func(string) bool + want []string + }{ + { + name: "length > 2", + input: []string{"go", "java", "c", "rust"}, + filterFn: func(s string) bool { return len(s) > 2 }, + want: []string{"java", "rust"}, + }, + { + name: "empty input", + input: []string{}, + filterFn: func(s string) bool { return len(s) > 0 }, + want: []string{}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := Filter(tc.input, tc.filterFn) + assert.Equal(t, tc.want, got) + }) + } +}