ADDED:
* slicesx.First
* slicesx.FirstIndex
* slicesx.Remove
* slicesx.RemoveAll
* slicesx.RemoveReverse
This commit is contained in:
brent saner
2026-09-03 16:25:31 -04:00
parent 67bd30907e
commit f002766c74
4 changed files with 364 additions and 218 deletions
+146 -1
View File
@@ -1,10 +1,51 @@
package slicesx
import (
`slices`
)
/*
First returns the first item/element in slice s.
e will be the nil/zero value of the slice element type
if the slice length is 0 (including if s == nil).
*/
func First[S ~[]E, E any](s S) (e E) {
if len(s) == 0 {
return
}
e = s[0]
return
}
/*
FirstIndex returns the index of the first element in slice s.
While at first glance this may seem useless, it may have some usecases as instead of causing panics:
* If s is empty, idx will be -1.
* If s is nil, idx will be -2.
* Otherwise idx will ALWAYS be 0.
*/_
func FirstIndex[S ~[]E, E any](s S) (idx int) {
if s == nil {
idx = -2
} else if len(s) == 0 {
idx = -1
}
return
}
/*
Last returns the last item/element in slice s.
e will be the nil/zero value of the slice element type
if the slice length is 0.
if the slice length is 0 (including if s == nil).
*/
func Last[S ~[]E, E any](s S) (e E) {
@@ -41,3 +82,107 @@ func LastIndex[S ~[]E, E any](s S) (idx int) {
return
}
/*
Remove removes any values of value elem from slice s up to max number of elems.
If maxRemove is negative (< 0), start from the end instead.
This simply wraps [RemoveReverse]:
removed = slicesx.RemoveReverse(s, elem, uint(-maxRemove))
If maxRemove is exactly 0, remove ALL instances of elem.
If s is nil, removed will be nil as well.
Note that s will remain untouched, and removed will be a new slice.
*/
func Remove[S ~[]E, E comparable](s S, elem E, maxRemove int) (removed S) {
var idx int
if s == nil {
return
}
if len(s) == 0 {
removed = []E{}
return
}
removed = make(S, 0, len(s))
defer func() {
if removed != nil {
removed = slices.Clip(removed)
}
}()
if maxRemove < 0 {
removed = RemoveReverse(s, elem, uint(-maxRemove))
return
} else if maxRemove == 0 {
maxRemove = len(s)
}
for idx = range s {
if s[idx] == elem && maxRemove > 0 {
maxRemove--
continue
}
removed = append(removed, s[idx])
}
return
}
/*
RemoveAll is simply a convenience wrapper around [Remove], e.g.:
removed = slicesx.Remove(s, elem, 0)
*/
func RemoveAll[S ~[]E, E comparable](s S, elem E) (removed S) { return Remove(s, elem, 0) }
/*
RemoveReverse removes any values of value elem from slice s up to max number of elems in reverse order
(i.e. starting from the END of s).
If maxRemove is exactly 0, remove all instances of elem (via [RemoveAll]), i.e.:
removed = slicesx.RemoveAll(s, elem)
// or, more directly:
removed = slicesx.Remove(s, elem, 0)
If s is nil, removed will be nil as well.
Note that s will remain untouched, and removed will be a new slice.
*/
func RemoveReverse[S ~[]E, E comparable](s S, elem E, maxRemove uint) (removed S) {
var idx int
if s == nil {
return
}
if len(s) == 0 {
removed = []E{}
return
}
if maxRemove == 0 {
removed = RemoveAll(s, elem)
return
}
removed = make(S, 0, len(s))
for idx = len(s) - 1; idx >= 0; idx-- {
if s[idx] == elem && maxRemove > 0 {
maxRemove--
continue
}
removed = append(removed, s[idx])
}
removed = slices.Clip(removed)
slices.Reverse(removed)
return
}