Skip to content

Commit 693a34e

Browse files
ianlancetaylorgopherbot
authored andcommitted
slices: add DeleteFunc
Fixes #54768 Change-Id: I588ae33c13e0bbd9d324c11771667b22a864047d Reviewed-on: https://go-review.googlesource.com/c/go/+/483175 Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Eli Bendersky <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]>
1 parent b3bc862 commit 693a34e

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

api/next/54768.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg slices, func DeleteFunc[$0 interface{ ~[]$1 }, $1 interface{}]($0, func($1) bool) $0 #54768

src/slices/slices.go

+26
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,32 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
109109
return append(s[:i], s[j:]...)
110110
}
111111

112+
// DeleteFunc removes any elements from s for which del returns true,
113+
// returning the modified slice.
114+
// DeleteFunc modifies the contents of the slice s;
115+
// it does not create a new slice.
116+
// When DeleteFunc removes m elements, it might not modify the elements
117+
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
118+
// zeroing those elements so that objects they reference can be garbage
119+
// collected.
120+
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
121+
// Don't start copying elements until we find one to delete.
122+
for i, v := range s {
123+
if del(v) {
124+
j := i
125+
for i++; i < len(s); i++ {
126+
v = s[i]
127+
if !del(v) {
128+
s[j] = v
129+
j++
130+
}
131+
}
132+
return s[:j]
133+
}
134+
}
135+
return s
136+
}
137+
112138
// Replace replaces the elements s[i:j] by the given v, and returns the
113139
// modified slice. Replace panics if s[i:j] is not a valid slice of s.
114140
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {

src/slices/slices_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,52 @@ func TestDelete(t *testing.T) {
304304
}
305305
}
306306

307+
var deleteFuncTests = []struct {
308+
s []int
309+
fn func(int) bool
310+
want []int
311+
}{
312+
{
313+
nil,
314+
func(int) bool { return true },
315+
nil,
316+
},
317+
{
318+
[]int{1, 2, 3},
319+
func(int) bool { return true },
320+
nil,
321+
},
322+
{
323+
[]int{1, 2, 3},
324+
func(int) bool { return false },
325+
[]int{1, 2, 3},
326+
},
327+
{
328+
[]int{1, 2, 3},
329+
func(i int) bool { return i > 2 },
330+
[]int{1, 2},
331+
},
332+
{
333+
[]int{1, 2, 3},
334+
func(i int) bool { return i < 2 },
335+
[]int{2, 3},
336+
},
337+
{
338+
[]int{10, 2, 30},
339+
func(i int) bool { return i >= 10 },
340+
[]int{2},
341+
},
342+
}
343+
344+
func TestDeleteFunc(t *testing.T) {
345+
for i, test := range deleteFuncTests {
346+
copy := Clone(test.s)
347+
if got := DeleteFunc(copy, test.fn); !Equal(got, test.want) {
348+
t.Errorf("DeleteFunc case %d: got %v, want %v", i, got, test.want)
349+
}
350+
}
351+
}
352+
307353
func panics(f func()) (b bool) {
308354
defer func() {
309355
if x := recover(); x != nil {

0 commit comments

Comments
 (0)