Skip to content

Commit

Permalink
slices: add DeleteFunc
Browse files Browse the repository at this point in the history
DeleteFunc was added to the standard library for the 1.21 release.
Add it here in x/exp for people still using earlier releases.

For golang/go#54768
Fixes golang/go#61327

Change-Id: I3c37051c289f46b0068bc1ee5da610149c59cd22
Reviewed-on: https://go-review.googlesource.com/c/exp/+/509236
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Eli Bendersky <eliben@google.com>
  • Loading branch information
ianlancetaylor authored and gopherbot committed Jul 13, 2023
1 parent 06a737e commit 613f0c0
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
24 changes: 24 additions & 0 deletions slices/slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,30 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
return append(s[:i], s[j:]...)
}

// DeleteFunc removes any elements from s for which del returns true,
// returning the modified slice.
// When DeleteFunc removes m elements, it might not modify the elements
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage
// collected.
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
// Don't start copying elements until we find one to delete.
for i, v := range s {
if del(v) {
j := i
for i++; i < len(s); i++ {
v = s[i]
if !del(v) {
s[j] = v
j++
}
}
return s[:j]
}
}
return s
}

// Replace replaces the elements s[i:j] by the given v, and returns the
// modified slice. Replace panics if s[i:j] is not a valid slice of s.
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
Expand Down
46 changes: 46 additions & 0 deletions slices/slices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,52 @@ func TestDelete(t *testing.T) {
}
}

var deleteFuncTests = []struct {
s []int
fn func(int) bool
want []int
}{
{
nil,
func(int) bool { return true },
nil,
},
{
[]int{1, 2, 3},
func(int) bool { return true },
nil,
},
{
[]int{1, 2, 3},
func(int) bool { return false },
[]int{1, 2, 3},
},
{
[]int{1, 2, 3},
func(i int) bool { return i > 2 },
[]int{1, 2},
},
{
[]int{1, 2, 3},
func(i int) bool { return i < 2 },
[]int{2, 3},
},
{
[]int{10, 2, 30},
func(i int) bool { return i >= 10 },
[]int{2},
},
}

func TestDeleteFunc(t *testing.T) {
for i, test := range deleteFuncTests {
copy := Clone(test.s)
if got := DeleteFunc(copy, test.fn); !Equal(got, test.want) {
t.Errorf("DeleteFunc case %d: got %v, want %v", i, got, test.want)
}
}
}

func panics(f func()) (b bool) {
defer func() {
if x := recover(); x != nil {
Expand Down

0 comments on commit 613f0c0

Please sign in to comment.