diff --git a/api/next/67326.txt b/api/next/67326.txt new file mode 100644 index 00000000000000..8b315915586e32 --- /dev/null +++ b/api/next/67326.txt @@ -0,0 +1 @@ +pkg slices, func Partition[$0 interface{ ~[]$1 }, $1 interface{}]($0, func($1) bool) ([]$1, []$1) #67326 diff --git a/doc/next/6-stdlib/99-minor/slices/67326.md b/doc/next/6-stdlib/99-minor/slices/67326.md new file mode 100644 index 00000000000000..846a53bae9f57c --- /dev/null +++ b/doc/next/6-stdlib/99-minor/slices/67326.md @@ -0,0 +1,4 @@ +The [Partition] function split original slice into two sub-slices +by given predicate. +The elements in the first slice all satisfy the predicate. +The elements of the second slice none satisfy the predicate. diff --git a/src/slices/example_test.go b/src/slices/example_test.go index cb601ada0ade65..646235240d91c3 100644 --- a/src/slices/example_test.go +++ b/src/slices/example_test.go @@ -411,3 +411,13 @@ func ExampleChunk() { // [{Bob 5} {Vera 24}] // [{Zac 15}] } + +func ExamplePartition() { + truthSlice, falseSlice := Partition([]int{1, 2, 3, 4, 5, 6}, func(x int) bool { return x%2 == 0 }) + fmt.Println(truthSlice) + fmt.Println(falseSlice) + + // Output: + // [2 4 6] + // [1 3 5] +} diff --git a/src/slices/slices.go b/src/slices/slices.go index 857ab46314324b..27ccc3a4afd1b4 100644 --- a/src/slices/slices.go +++ b/src/slices/slices.go @@ -506,3 +506,19 @@ func Repeat[S ~[]E, E any](x S, count int) S { } return newslice } + +// Partition split the original slice into two slice. +// The elements of the first slice all satisfy the predicate. +// The elements of the second slice none satisfy the predicate. +func Partition[Slice ~[]E, E any](s Slice, f func(E) bool) ([]E, []E) { + truthSlice := make([]E, 0) + falseSlice := make([]E, 0) + for _, x := range s { + if f(x) { + truthSlice = append(truthSlice, x) + } else { + falseSlice = append(falseSlice, x) + } + } + return truthSlice, falseSlice +} diff --git a/src/slices/slices_test.go b/src/slices/slices_test.go index 68c8a3adc252f0..e877973571aa73 100644 --- a/src/slices/slices_test.go +++ b/src/slices/slices_test.go @@ -1450,3 +1450,37 @@ func TestRepeatPanics(t *testing.T) { } } } + +func TestPartition(t *testing.T) { + tests := []struct { + name string + original []int + truthSlice []int + falseSlice []int + predicate func(int) bool + }{ + { + name: "split odd & even", + original: []int{1, 2, 3, 4, 5, 6}, + truthSlice: []int{1, 3, 5}, + falseSlice: []int{2, 4, 6}, + predicate: func(x int) bool { return x%2 == 1 }, + }, + { + name: "split by pivot", + original: []int{1, 10, 100, 1000, 10000}, + truthSlice: []int{1, 10}, + falseSlice: []int{100, 1000, 10000}, + predicate: func(x int) bool { return x < 100 }, + }, + } + for _, testCase := range tests { + truthSlice, falseSlice := Partition(testCase.original, testCase.predicate) + if !Equal(truthSlice, testCase.truthSlice) { + t.Errorf("Partition %s truth failed", testCase.name) + } + if !Equal(falseSlice, testCase.falseSlice) { + t.Errorf("Parition %s false failed", testCase.name) + } + } +}