1 // Copyright 2021 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package slices defines various functions useful with slices of any type.
8 // Equal reports whether two slices are equal: the same length and all
9 // elements equal. If the lengths are different, Equal returns false.
10 // Otherwise, the elements are compared in increasing index order, and the
11 // comparison stops at the first unequal pair.
12 // Floating point NaNs are not considered equal.
13 func Equal[E comparable](s1, s2 []E) bool {
14 if len(s1) != len(s2) {
25 // EqualFunc reports whether two slices are equal using a comparison
26 // function on each pair of elements. If the lengths are different,
27 // EqualFunc returns false. Otherwise, the elements are compared in
28 // increasing index order, and the comparison stops at the first index
29 // for which eq returns false.
30 func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool {
31 if len(s1) != len(s2) {
34 for i, v1 := range s1 {
43 // Index returns the index of the first occurrence of v in s,
44 // or -1 if not present.
45 func Index[E comparable](s []E, v E) int {
54 // IndexFunc returns the first index i satisfying f(s[i]),
56 func IndexFunc[E any](s []E, f func(E) bool) int {
65 // Contains reports whether v is present in s.
66 func Contains[E comparable](s []E, v E) bool {
67 return Index(s, v) >= 0
70 // ContainsFunc reports whether at least one
71 // element e of s satisfies f(e).
72 func ContainsFunc[E any](s []E, f func(E) bool) bool {
73 return IndexFunc(s, f) >= 0
76 // Insert inserts the values v... into s at index i,
77 // returning the modified slice.
78 // The elements at s[i:] are shifted up to make room.
79 // In the returned slice r, r[i] == v[0],
80 // and r[i+len(v)] == value originally at r[i].
81 // Insert panics if i is out of range.
82 // This function is O(len(s) + len(v)).
83 func Insert[S ~[]E, E any](s S, i int, v ...E) S {
84 tot := len(s) + len(v)
87 copy(s2[i+len(v):], s[i:])
91 // Use append rather than make so that we bump the size of
92 // the slice up to the next storage class.
93 // This is what Grow does but we don't call Grow because
94 // that might copy the values twice.
95 s2 := append(S(nil), make(S, tot)...)
98 copy(s2[i+len(v):], s[i:])
102 // Delete removes the elements s[i:j] from s, returning the modified slice.
103 // Delete panics if s[i:j] is not a valid slice of s.
104 // Delete modifies the contents of the slice s; it does not create a new slice.
105 // Delete is O(len(s)-j), so if many items must be deleted, it is better to
106 // make a single call deleting them all together than to delete one at a time.
107 // Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those
108 // elements contain pointers you might consider zeroing those elements so that
109 // objects they reference can be garbage collected.
110 func Delete[S ~[]E, E any](s S, i, j int) S {
111 _ = s[i:j] // bounds check
113 return append(s[:i], s[j:]...)
116 // DeleteFunc removes any elements from s for which del returns true,
117 // returning the modified slice.
118 // DeleteFunc modifies the contents of the slice s;
119 // it does not create a new slice.
120 // When DeleteFunc removes m elements, it might not modify the elements
121 // s[len(s)-m:len(s)]. If those elements contain pointers you might consider
122 // zeroing those elements so that objects they reference can be garbage
124 func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
125 // Don't start copying elements until we find one to delete.
126 for i, v := range s {
129 for i++; i < len(s); i++ {
142 // Replace replaces the elements s[i:j] by the given v, and returns the
143 // modified slice. Replace panics if s[i:j] is not a valid slice of s.
144 func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
145 _ = s[i:j] // verify that i:j is a valid subslice
146 tot := len(s[:i]) + len(v) + len(s[j:])
149 copy(s2[i+len(v):], s[j:])
156 copy(s2[i+len(v):], s[j:])
160 // Clone returns a copy of the slice.
161 // The elements are copied using assignment, so this is a shallow clone.
162 func Clone[S ~[]E, E any](s S) S {
163 // Preserve nil in case it matters.
167 return append(S([]E{}), s...)
170 // Compact replaces consecutive runs of equal elements with a single copy.
171 // This is like the uniq command found on Unix.
172 // Compact modifies the contents of the slice s; it does not create a new slice.
173 // When Compact discards m elements in total, 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 collected.
176 func Compact[S ~[]E, E comparable](s S) S {
181 for k := 1; k < len(s); k++ {
192 // CompactFunc is like Compact but uses a comparison function.
193 func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
198 for k := 1; k < len(s); k++ {
199 if !eq(s[k], s[k-1]) {
209 // Grow increases the slice's capacity, if necessary, to guarantee space for
210 // another n elements. After Grow(n), at least n elements can be appended
211 // to the slice without another allocation. If n is negative or too large to
212 // allocate the memory, Grow panics.
213 func Grow[S ~[]E, E any](s S, n int) S {
215 panic("cannot be negative")
217 if n -= cap(s) - len(s); n > 0 {
218 s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
223 // Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
224 func Clip[S ~[]E, E any](s S) S {
225 return s[:len(s):len(s)]