github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/snm/snm.go (about) 1 // Package snm provides convenience functions for slices and maps. 2 package snm 3 4 import ( 5 "cmp" 6 "slices" 7 8 "golang.org/x/exp/constraints" 9 "golang.org/x/exp/maps" 10 ) 11 12 // Slice returns a new slice of size n whose values are the results 13 // of applying f on each index. 14 func Slice[T any](n int, f func(int) T) []T { 15 s := make([]T, n) 16 for i := range s { 17 s[i] = f(i) 18 } 19 return s 20 } 21 22 // SliceToSlice returns a slice of the same length containing the results 23 // of applying f to the elements of s. 24 func SliceToSlice[A any, B any](a []A, f func(A) B) []B { 25 b := make([]B, len(a)) 26 for i := range a { 27 b[i] = f(a[i]) 28 } 29 return b 30 } 31 32 // MapToMap returns a map containing the results of applying f to the key-value 33 // pairs of m. 34 // f should return a new key-value pair for the new map. 35 // Keys that appear more than once will override each other. 36 func MapToMap[K comparable, V any, K2 comparable, V2 any]( 37 m map[K]V, f func(K, V) (K2, V2)) map[K2]V2 { 38 mm := make(map[K2]V2, len(m)) 39 for k, v := range m { 40 k2, v2 := f(k, v) 41 mm[k2] = v2 42 } 43 return mm 44 } 45 46 // FilterSlice returns a new slice containing only the elements 47 // for which keep returns true. 48 func FilterSlice[S any](s []S, keep func(S) bool) []S { 49 var result []S 50 for _, e := range s { 51 if keep(e) { 52 result = append(result, e) 53 } 54 } 55 return result 56 } 57 58 // FilterMap returns a new map containing only the elements 59 // for which keep returns true. 60 func FilterMap[K comparable, V any](m map[K]V, keep func(k K, v V) bool) map[K]V { 61 mm := map[K]V{} 62 for k, v := range m { 63 if keep(k, v) { 64 mm[k] = v 65 } 66 } 67 return mm 68 } 69 70 // Sorted sorts the input and returns it. 71 func Sorted[T constraints.Ordered](s []T) []T { 72 slices.Sort(s) 73 return s 74 } 75 76 // SortedFunc sorts the input and returns it. 77 func SortedFunc[T any](s []T, cmp func(T, T) int) []T { 78 slices.SortFunc(s, cmp) 79 return s 80 } 81 82 // At returns the elements of t at the indexes in at. 83 func At[T any, I constraints.Integer](t []T, at []I) []T { 84 result := make([]T, 0, len(at)) 85 for _, i := range at { 86 result = append(result, t[i]) 87 } 88 return result 89 } 90 91 // DefaultMap wraps a map with a function that generates values for missing keys. 92 type DefaultMap[K comparable, V any] struct { 93 M map[K]V // Underlying map. Can be safely read from and written to. 94 F func(K) V // Generator function. 95 } 96 97 // Get returns the value associated with key k. 98 // If k is missing from the map, the generator function is called with k and the 99 // result becomes k's value. 100 func (m DefaultMap[K, V]) Get(k K) V { 101 if v, ok := m.M[k]; ok { 102 return v 103 } 104 v := m.F(k) 105 m.M[k] = v 106 return v 107 } 108 109 // Set sets v as k's value. 110 func (m DefaultMap[K, V]) Set(k K, v V) { 111 m.M[k] = v 112 } 113 114 // NewDefaultMap returns an empty map with the given function as the missing 115 // value generator. 116 func NewDefaultMap[K comparable, V any](f func(K) V) DefaultMap[K, V] { 117 return DefaultMap[K, V]{map[K]V{}, f} 118 } 119 120 // Compare is a generic comparator function for ordered types. 121 // 122 // Deprecated: use [cmp.Compare] instead. 123 func Compare[T constraints.Ordered](a, b T) int { 124 if a < b { 125 return -1 126 } 127 if a > b { 128 return 1 129 } 130 return 0 131 } 132 133 // CompareReverse orders values from big to small. 134 // Should be generally used as a parameter, not called. 135 func CompareReverse[T constraints.Ordered](a, b T) int { 136 return -1 * cmp.Compare(a, b) 137 } 138 139 // SortedKeys sorts a map's keys according to their values' natural order. 140 func SortedKeys[K comparable, V constraints.Ordered]( 141 m map[K]V) []K { 142 return SortedFunc(maps.Keys(m), func(a, b K) int { 143 return Compare(m[a], m[b]) 144 }) 145 } 146 147 // SortedKeysFunc sorts a map's keys by comparing their values. 148 func SortedKeysFunc[K comparable, V constraints.Ordered]( 149 m map[K]V, cmp func(V, V) int) []K { 150 return SortedFunc(maps.Keys(m), func(a, b K) int { 151 return cmp(m[a], m[b]) 152 }) 153 } 154 155 // Number is an integer or a float. 156 type Number interface { 157 constraints.Integer | constraints.Float 158 } 159 160 // Cast casts each element in the slice. 161 func Cast[TO Number, FROM Number](s []FROM) []TO { 162 return SliceToSlice(s, func(x FROM) TO { return TO(x) }) 163 }