github.com/sridharv/stencil@v0.0.0-20170626103218-a81b4a7626a1/std/slice/slice.go (about) 1 // Package slice implements operations on slices. 2 // 3 // All operations act on slices of T. Use stencil to specialise to a type. 4 // 5 // For example, in order to use a string version of this package, import it as 6 // 7 // import ( 8 // str_slice "github.com/sridharv/stencil/std/slice/T/string" 9 // ) 10 // 11 // and run stencil on the importing package. 12 package slice 13 14 import ( 15 "reflect" 16 "sort" 17 ) 18 19 type T interface{} 20 21 // Any returns true if fn is true for any elements of s 22 func Any(s []T, fn func(T) bool) bool { 23 return IndexFunc(s, fn) != -1 24 } 25 26 // Any returns true if fn is true for all elements of s 27 func All(s []T, fn func(T) bool) bool { 28 return IndexFunc(s, func(e T) bool { return !fn(e) }) == -1 29 } 30 31 // IndexFunc returns the index of the first element for which fn returns true. 32 // If no such element exists it returns -1. 33 func IndexFunc(s []T, fn func(T) bool) int { 34 for i, e := range s { 35 if fn(e) { 36 return i 37 } 38 } 39 return -1 40 } 41 42 // Index returns the first index of e in s 43 func Index(s []T, e T) int { 44 return IndexFunc(s, func(el T) bool { return el == e }) 45 } 46 47 var ( 48 zero T 49 needsGC = typeNeedsGC(reflect.TypeOf(zero)) 50 ) 51 52 func typeNeedsGC(t reflect.Type) bool { 53 switch t.Kind() { 54 case reflect.Map, reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Slice: 55 return true 56 case reflect.Struct: 57 n := t.NumField() 58 for i := 0; i < n; i++ { 59 if typeNeedsGC(t.Field(i).Type) { 60 return true 61 } 62 } 63 return false 64 default: 65 return false 66 } 67 } 68 69 // The following are taken from https://github.com/golang/go/wiki/SliceTricks 70 // 71 // Cut, Delete, DeleteUnordered, Push, Pop, Reverse, Insert, InsertSlice 72 73 // Cut removes all elements between i and j. 74 func Cut(a []T, i, j int) []T { 75 if !needsGC { 76 return append(a[:i], a[j:]...) 77 } 78 copy(a[i:], a[j:]) 79 for k, n := len(a)-j+i, len(a); k < n; k++ { 80 a[k] = zero 81 } 82 return a[:len(a)-j+i] 83 } 84 85 // Delete removes the ith element from a and returns the resulting slice. 86 func Delete(a []T, i int) []T { 87 return Cut(a, i, i+1) 88 } 89 90 // DeleteUnordered removes the ith element in a, without preserving order. It can be faster that 91 // Delete as it results in much fewer copies. 92 func DeleteUnordered(a []T, i int) []T { 93 a[i] = a[len(a)-1] 94 a[len(a)-1] = zero 95 return a[:len(a)-1] 96 } 97 98 // Insert inserts v in a at index i and returns the new slice 99 func Insert(a []T, v T, i int) []T { 100 a = append(a, zero) 101 copy(a[i+1:], a[i:]) 102 a[i] = v 103 return a 104 } 105 106 // InsertSlice inserts v into a at index i and returns the new slice 107 func InsertSlice(a []T, v []T, i int) []T { 108 return append(a[:i], append(v, a[i:]...)...) 109 } 110 111 // Push pushes v on to the end of a, returning an updated slice. 112 func Push(a []T, v T) []T { 113 return append(a, v) 114 } 115 116 // Pop removes the last element from a, returning an updating slice 117 func Pop(a []T) (T, []T) { 118 return a[len(a)-1], a[:len(a)-1] 119 } 120 121 // Reverse reverses a in place. 122 func Reverse(a []T) { 123 for l, r := 0, len(a)-1; l < r; l, r = l+1, r-1 { 124 a[l], a[r] = a[r], a[l] 125 } 126 } 127 128 type sorter struct { 129 a []T 130 less func(a, b T) bool 131 } 132 133 func (s *sorter) Len() int { return len(s.a) } 134 func (s *sorter) Less(i, j int) bool { return s.less(s.a[i], s.a[j]) } 135 func (s *sorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] } 136 137 // Sort sorts a using the comparison function less. 138 func Sort(a []T, less func(a, b T) bool) { 139 sort.Sort(&sorter{a, less}) 140 } 141 142 // SortStable sorts a stably using the comparison function less. 143 func SortStable(a []T, less func(a, b T) bool) { 144 sort.Stable(&sorter{a, less}) 145 } 146 147 // Flatten returns a slice created by adding each element of each slice in slices 148 func Flatten(slices ...[]T) []T { 149 var a []T 150 for _, s := range slices { 151 a = append(a, s...) 152 } 153 return a 154 }