maps.go (3144B)
1 // Copyright 2023 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. 4 5 // Package moremaps contains more functions for working with maps. 6 package moremaps 7 8 import ( 9 "cmp" 10 "iter" 11 "maps" 12 "slices" 13 ) 14 15 // Arbitrary returns an arbitrary (key, value) entry from the map and ok is true, if 16 // the map is not empty. Otherwise, it returns zero values for K and V, and false. 17 func Arbitrary[K comparable, V any](m map[K]V) (_ K, _ V, ok bool) { 18 for k, v := range m { 19 return k, v, true 20 } 21 return 22 } 23 24 // Group returns a new non-nil map containing the elements of s grouped by the 25 // keys returned from the key func. 26 func Group[K comparable, V any](s []V, key func(V) K) map[K][]V { 27 m := make(map[K][]V) 28 for _, v := range s { 29 k := key(v) 30 m[k] = append(m[k], v) 31 } 32 return m 33 } 34 35 // KeySlice returns the keys of the map M, like slices.Collect(maps.Keys(m)). 36 func KeySlice[M ~map[K]V, K comparable, V any](m M) []K { 37 r := make([]K, 0, len(m)) 38 for k := range m { 39 r = append(r, k) 40 } 41 return r 42 } 43 44 // ValueSlice returns the values of the map M, like slices.Collect(maps.Values(m)). 45 func ValueSlice[M ~map[K]V, K comparable, V any](m M) []V { 46 r := make([]V, 0, len(m)) 47 for _, v := range m { 48 r = append(r, v) 49 } 50 return r 51 } 52 53 // SameKeys reports whether x and y have equal sets of keys. 54 func SameKeys[K comparable, V1, V2 any](x map[K]V1, y map[K]V2) bool { 55 ignoreValues := func(V1, V2) bool { return true } 56 return maps.EqualFunc(x, y, ignoreValues) 57 } 58 59 // Sorted returns an iterator over the entries of m in key order. 60 func Sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V] { 61 // TODO(adonovan): use maps.Sorted if proposal #68598 is accepted. 62 return func(yield func(K, V) bool) { 63 keys := KeySlice(m) 64 slices.Sort(keys) 65 for _, k := range keys { 66 if !yield(k, m[k]) { 67 break 68 } 69 } 70 } 71 } 72 73 // SortedFunc returns an iterator over the entries of m in the key order determined by cmp. 74 func SortedFunc[M ~map[K]V, K comparable, V any](m M, cmp func(x, y K) int) iter.Seq2[K, V] { 75 // TODO(adonovan): use maps.SortedFunc if proposal #68598 is accepted. 76 return func(yield func(K, V) bool) { 77 keys := KeySlice(m) 78 slices.SortFunc(keys, cmp) 79 for _, k := range keys { 80 if !yield(k, m[k]) { 81 break 82 } 83 } 84 } 85 } 86 87 // Delete is like delete(m, k) but reports whether deletion occurred. 88 func Delete[M ~map[K]V, K comparable, V any](m M, k K) bool { 89 pre := len(m) 90 delete(m, k) 91 return pre != len(m) 92 } 93 94 // Entry is a key-value pair obtained from a map. 95 type Entry[K comparable, V any] struct { 96 Key K 97 Value V 98 } 99 100 // Entries returns a new unordered array of the entries of a map. 101 func Entries[M ~map[K]V, K comparable, V any](m M) []Entry[K, V] { 102 entries := make([]Entry[K, V], 0, len(m)) 103 for k, v := range m { 104 entries = append(entries, Entry[K, V]{k, v}) 105 } 106 return entries 107 } 108 109 // FromEntries returns a new map into which the entries have been inserted in order. 110 func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V { 111 m := make(map[K]V, len(entries)) 112 for _, e := range entries { 113 m[e.Key] = e.Value 114 } 115 return m 116 }