github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/easy/maps.go (about) 1 package easy 2 3 // DiffMaps returns a new map which contains elements which present in m, 4 // but not present in others. 5 // 6 // If length of m is zero, it returns nil. 7 func DiffMaps[M ~map[K]V, K comparable, V any](m M, others ...M) M { 8 out := make(M) 9 for k, v := range m { 10 found := false 11 for _, b := range others { 12 if _, ok := b[k]; ok { 13 found = true 14 break 15 } 16 } 17 if !found { 18 out[k] = v 19 } 20 } 21 return out 22 } 23 24 // DiffMapsInplace removes elements that present in others from m. 25 func DiffMapsInplace[M ~map[K]V, K comparable, V any](m M, others ...M) M { 26 for k := range m { 27 for _, m1 := range others { 28 if _, ok := m1[k]; ok { 29 delete(m, k) 30 break 31 } 32 } 33 } 34 return m 35 } 36 37 // FilterMaps iterates the given maps, it calls predicate(k, v) for each 38 // key value in the maps and returns a new map of key value pairs for 39 // which predicate(k, v) returns true. 40 func FilterMaps[M ~map[K]V, K comparable, V any](predicate func(k K, v V) bool, maps ...M) M { 41 if len(maps) == 0 { 42 return nil 43 } 44 out := make(M, len(maps[0])) 45 for _, x := range maps { 46 for k, v := range x { 47 if predicate(k, v) { 48 out[k] = v 49 } 50 } 51 } 52 return out 53 } 54 55 // MergeMaps returns a new map containing all key values present in given maps. 56 func MergeMaps[M ~map[K]V, K comparable, V any](maps ...M) M { 57 var length int 58 for _, m := range maps { 59 length += len(m) 60 } 61 dst := make(M, length) 62 for _, m := range maps { 63 for k, v := range m { 64 dst[k] = v 65 } 66 } 67 return dst 68 } 69 70 // MergeMapsTo adds key values present in others to the dst map. 71 // If dst is a nil map, it creates a new map and returns it. 72 func MergeMapsTo[M ~map[K]V, K comparable, V any](dst M, others ...M) M { 73 if len(others) == 0 { 74 return dst 75 } 76 if dst == nil { 77 dst = make(M, len(others[0])) 78 } 79 for _, m := range others { 80 for k, v := range m { 81 dst[k] = v 82 } 83 } 84 return dst 85 } 86 87 // MergeMapsToPtr is similar to MergeMapsTo, but it accepts a pointer as dst, 88 // if dst points to a nil map, it creates a new map and assigns it to dst. 89 // If dst is a nil pointer, it panics. 90 func MergeMapsToPtr[M ~map[K]V, K comparable, V any](dst *M, others ...M) { 91 if dst == nil { 92 panic("easy.MergeMapsToPtr: dst must not be nil") 93 } 94 *dst = MergeMapsTo(*dst, others...) 95 } 96 97 // Keys returns the keys of the map m. 98 // The keys will be in an indeterminate order. 99 // 100 // Optionally, a filter function can be given to make it returning 101 // only keys for which filter(k, v) returns true. 102 func Keys[M ~map[K]V, K comparable, V any](m M, filter ...func(K, V) bool) []K { 103 var f func(K, V) bool 104 if len(filter) > 0 { 105 f = filter[0] 106 } 107 keys := make([]K, 0, len(m)) 108 if f == nil { 109 for k := range m { 110 keys = append(keys, k) 111 } 112 } else { 113 for k, v := range m { 114 if f(k, v) { 115 keys = append(keys, k) 116 } 117 } 118 } 119 return keys 120 } 121 122 // Values returns the values of the map m. 123 // The values will be in an indeterminate order. 124 // 125 // Optionally, a filter function can be given to make it returning 126 // only values for which filter(k, v) returns true. 127 func Values[M ~map[K]V, K comparable, V any](m M, filter ...func(K, V) bool) []V { 128 var f func(K, V) bool 129 if len(filter) > 0 { 130 f = filter[0] 131 } 132 values := make([]V, 0, len(m)) 133 if f == nil { 134 for _, v := range m { 135 values = append(values, v) 136 } 137 } else { 138 for k, v := range m { 139 if f(k, v) { 140 values = append(values, v) 141 } 142 } 143 } 144 return values 145 } 146 147 // CopyMap copies a map to be a new one. 148 // optionalSize optionally specifies the size of the new map. 149 func CopyMap[M ~map[K]V, K comparable, V any](m M, optionalSize ...int) M { 150 copySize := len(m) 151 if len(optionalSize) > 0 && optionalSize[0] > copySize { 152 copySize = optionalSize[0] 153 } 154 out := make(M, copySize) 155 for k, v := range m { 156 out[k] = v 157 } 158 return out 159 } 160 161 // SplitMap splits a large map to batches, it returns a slice 162 // of type []M whose elements are subset of the given map. 163 func SplitMap[M ~map[K]V, K comparable, V any](m M, batchSize int) []M { 164 if len(m) == 0 { 165 return nil 166 } 167 if len(m) <= batchSize { 168 return []M{m} 169 } 170 171 cnt := (len(m) + batchSize - 1) / batchSize 172 out := make([]M, cnt) 173 for i := range out { 174 if i < len(out)-1 { 175 out[i] = make(M, batchSize) 176 } else { 177 out[i] = make(M, len(m)%batchSize) 178 } 179 } 180 i := 0 181 for k, v := range m { 182 out[i/batchSize][k] = v 183 i++ 184 } 185 return out 186 }