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 (including if s == nil). */ func Last[S ~[]E, E any](s S) (e E) { var idx int = LastIndex(s) if idx < 0 { return } e = s[idx] return } /* LastIndex returns the index of the last element in slice s. If s is empty, idx will be -1. If s is nil, idx will be -2. */ func LastIndex[S ~[]E, E any](s S) (idx int) { var l int = len(s) idx = -2 if s != nil { idx++ } if l == 0 { return } idx = l - 1 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 }