Skip to content

Commit 613f0c0

Browse files
ianlancetaylorgopherbot
authored andcommitted
slices: add DeleteFunc
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 <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Eli Bendersky <[email protected]>
1 parent 06a737e commit 613f0c0

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

slices/slices.go

+24
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,30 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
168168
return append(s[:i], s[j:]...)
169169
}
170170

171+
// DeleteFunc removes any elements from s for which del returns true,
172+
// returning the modified slice.
173+
// When DeleteFunc removes m elements, it might not modify the elements
174+
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
175+
// zeroing those elements so that objects they reference can be garbage
176+
// collected.
177+
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
178+
// Don't start copying elements until we find one to delete.
179+
for i, v := range s {
180+
if del(v) {
181+
j := i
182+
for i++; i < len(s); i++ {
183+
v = s[i]
184+
if !del(v) {
185+
s[j] = v
186+
j++
187+
}
188+
}
189+
return s[:j]
190+
}
191+
}
192+
return s
193+
}
194+
171195
// Replace replaces the elements s[i:j] by the given v, and returns the
172196
// modified slice. Replace panics if s[i:j] is not a valid slice of s.
173197
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {

slices/slices_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,52 @@ func TestDelete(t *testing.T) {
498498
}
499499
}
500500

501+
var deleteFuncTests = []struct {
502+
s []int
503+
fn func(int) bool
504+
want []int
505+
}{
506+
{
507+
nil,
508+
func(int) bool { return true },
509+
nil,
510+
},
511+
{
512+
[]int{1, 2, 3},
513+
func(int) bool { return true },
514+
nil,
515+
},
516+
{
517+
[]int{1, 2, 3},
518+
func(int) bool { return false },
519+
[]int{1, 2, 3},
520+
},
521+
{
522+
[]int{1, 2, 3},
523+
func(i int) bool { return i > 2 },
524+
[]int{1, 2},
525+
},
526+
{
527+
[]int{1, 2, 3},
528+
func(i int) bool { return i < 2 },
529+
[]int{2, 3},
530+
},
531+
{
532+
[]int{10, 2, 30},
533+
func(i int) bool { return i >= 10 },
534+
[]int{2},
535+
},
536+
}
537+
538+
func TestDeleteFunc(t *testing.T) {
539+
for i, test := range deleteFuncTests {
540+
copy := Clone(test.s)
541+
if got := DeleteFunc(copy, test.fn); !Equal(got, test.want) {
542+
t.Errorf("DeleteFunc case %d: got %v, want %v", i, got, test.want)
543+
}
544+
}
545+
}
546+
501547
func panics(f func()) (b bool) {
502548
defer func() {
503549
if x := recover(); x != nil {

0 commit comments

Comments
 (0)