Skip to content

slices: add Partition #67327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/next/67326.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg slices, func Partition[$0 interface{ ~[]$1 }, $1 interface{}]($0, func($1) bool) ([]$1, []$1) #67326
4 changes: 4 additions & 0 deletions doc/next/6-stdlib/99-minor/slices/67326.md
Original file line number Diff line number Diff line change
@@ -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.
10 changes: 10 additions & 0 deletions src/slices/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}
16 changes: 16 additions & 0 deletions src/slices/slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
34 changes: 34 additions & 0 deletions src/slices/slices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}