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 {
46 for i, vs := range s {
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:])
94 copy(s2[i+len(v):], s[i:])
98 // Delete removes the elements s[i:j] from s, returning the modified slice.
99 // Delete panics if s[i:j] is not a valid slice of s.
100 // Delete modifies the contents of the slice s; it does not create a new slice.
101 // Delete is O(len(s)-j), so if many items must be deleted, it is better to
102 // make a single call deleting them all together than to delete one at a time.
103 // Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those
104 // elements contain pointers you might consider zeroing those elements so that
105 // objects they reference can be garbage collected.
106 func Delete[S ~[]E, E any](s S, i, j int) S {
107 _ = s[i:j] // bounds check
109 return append(s[:i], s[j:]...)
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
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 {
125 for i++; i < len(s); i++ {
138 // Replace replaces the elements s[i:j] by the given v, and returns the
139 // modified slice. Replace panics if s[i:j] is not a valid slice of s.
140 func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
141 _ = s[i:j] // verify that i:j is a valid subslice
142 tot := len(s[:i]) + len(v) + len(s[j:])
145 copy(s2[i+len(v):], s[j:])
152 copy(s2[i+len(v):], s[j:])
156 // Clone returns a copy of the slice.
157 // The elements are copied using assignment, so this is a shallow clone.
158 func Clone[S ~[]E, E any](s S) S {
159 // Preserve nil in case it matters.
163 return append(S([]E{}), s...)
166 // Compact replaces consecutive runs of equal elements with a single copy.
167 // This is like the uniq command found on Unix.
168 // Compact modifies the contents of the slice s; it does not create a new slice.
169 // When Compact discards m elements in total, it might not modify the elements
170 // s[len(s)-m:len(s)]. If those elements contain pointers you might consider
171 // zeroing those elements so that objects they reference can be garbage collected.
172 func Compact[S ~[]E, E comparable](s S) S {
178 for _, v := range s[1:] {
188 // CompactFunc is like Compact but uses a comparison function.
189 func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
195 for _, v := range s[1:] {
205 // Grow increases the slice's capacity, if necessary, to guarantee space for
206 // another n elements. After Grow(n), at least n elements can be appended
207 // to the slice without another allocation. If n is negative or too large to
208 // allocate the memory, Grow panics.
209 func Grow[S ~[]E, E any](s S, n int) S {
211 panic("cannot be negative")
213 if n -= cap(s) - len(s); n > 0 {
214 s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
219 // Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
220 func Clip[S ~[]E, E any](s S) S {
221 return s[:len(s):len(s)]