util/slicesx: add MapKeys and MapValues from golang.org/x/exp/maps

Importing the ~deprecated golang.org/x/exp/maps as "xmaps" to not
shadow the std "maps" was getting ugly.

And using slices.Collect on an iterator is verbose & allocates more.

So copy (x)maps.Keys+Values into our slicesx package instead.

Updates #cleanup
Updates #12912
Updates #14514 (pulled out of that change)

Change-Id: I5e68d12729934de93cf4a9cd87c367645f86123a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2025-01-03 10:41:02 -08:00
committed by Brad Fitzpatrick
parent 17b881538a
commit 1e2e319e7d
17 changed files with 76 additions and 41 deletions

View File

@@ -148,3 +148,43 @@ func FirstEqual[T comparable](s []T, v T) bool {
func LastEqual[T comparable](s []T, v T) bool {
return len(s) > 0 && s[len(s)-1] == v
}
// MapKeys returns the values of the map m.
//
// The keys will be in an indeterminate order.
//
// It's equivalent to golang.org/x/exp/maps.Keys, which
// unfortunately has the package name "maps", shadowing
// the std "maps" package. This version exists for clarity
// when reading call sites.
//
// As opposed to slices.Collect(maps.Keys(m)), this allocates
// the returned slice once to exactly the right size, rather than
// appending larger backing arrays as it goes.
func MapKeys[M ~map[K]V, K comparable, V any](m M) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
// MapValues returns the values of the map m.
//
// The values will be in an indeterminate order.
//
// It's equivalent to golang.org/x/exp/maps.Values, which
// unfortunately has the package name "maps", shadowing
// the std "maps" package. This version exists for clarity
// when reading call sites.
//
// As opposed to slices.Collect(maps.Values(m)), this allocates
// the returned slice once to exactly the right size, rather than
// appending larger backing arrays as it goes.
func MapValues[M ~map[K]V, K comparable, V any](m M) []V {
r := make([]V, 0, len(m))
for _, v := range m {
r = append(r, v)
}
return r
}