Skip to content

proposal: maps: add KeysSlice and ValuesSlice functions to extract map contents as slices #73291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
samsonkolge opened this issue Apr 9, 2025 · 2 comments
Labels
Milestone

Comments

@samsonkolge
Copy link

Proposal Details

Background

The maps package currently provides iterator-based functions (Keys and Values)
that return iterators over a map's keys or values. While iterators are powerful
and composable, they require extra code to convert to slices, which is a common
use case.

Converting map keys or values to slices is a recurring pattern in Go code.
Currently, developers need to write boilerplate like:

keys := make([]KeyType, 0, len(myMap))
for k := range myMap {
    keys = append(keys, k)
}

Proposal

Add two new functions to the maps package:

  1. KeysSlice[M ~map[K]V, K comparable, V any](m M) []K
  2. ValuesSlice[M ~map[K]V, K comparable, V any](m M) []V

These functions would extract map keys/values into slices, complementing the
existing iterator-based functions and providing a direct solution for the common
use case of converting map contents to slices.

Proposed Implementation

The implementation would be straightforward:

// KeysSlice returns a new slice containing the keys of m.
// The keys will be in an indeterminate order.
func KeysSlice[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
}

// ValuesSlice returns a new slice containing the values of m.
// The values will be in an indeterminate order.
func ValuesSlice[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
}

Use Cases

These functions would be useful for various common scenarios:

  1. Working with map keys in a sorted manner:

    keys := maps.KeysSlice(myMap)
    slices.Sort(keys)
    // Process keys in sorted order
  2. Getting a list of values for processing:

    values := maps.ValuesSlice(userRoles)
    for _, role := range values {
        // Process roles
    }
  3. Converting to a different representation:

    // Easily convert map values to a slice for API responses
    response.Items = maps.ValuesSlice(dataMap)

Alternatives Considered

  1. Using existing iterator functions:
    While Keys() and Values() combined with slices.Collect() can achieve
    similar functionality, this requires importing multiple packages and is less
    discoverable for users:

    keys := slices.Collect(maps.Keys(myMap))
  2. Using range with assignment:
    The current approach of manually creating slices and iterating is verbose and
    requires boilerplate code.

Compatibility

This change adds new functionality without modifying existing behavior, so it has
no compatibility concerns.

/cc @golang/maps-owners

@gopherbot gopherbot added this to the Proposal milestone Apr 9, 2025
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/664135 mentions this issue: This change adds two new helper functions to the maps package:

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/664136 mentions this issue: This change adds two new helper functions to the maps package:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants