How to sort a map first by value, then by key in Go

1 Answer

0 votes
package main

import (
    "cmp"
    "fmt"
    "slices"
)

// Pair represents a key-value entry for sorting purposes.
type Pair struct {
    Key   string
    Value int
}

/**
 * Sorts a Go map first by value (ascending), then by key (ascending) as a tie-breaker.
 * Returns a slice of Pair structs since Go maps cannot maintain a sorted order natively.
 */
func SortMapByValueThenKey(m map[string]int) []Pair {
    // 1. Convert map entries into a slice of Pair structs
    pairs := make([]Pair, 0, len(m))
    for k, v := range m {
        pairs = append(pairs, Pair{Key: k, Value: v})
    }

    // 2. Sort the slice using slices.SortFunc and the cmp package (Go 1.21+)
    slices.SortFunc(pairs, func(a, b Pair) int {
        // Primary sort: Ascending by value (score)
        if vCmp := cmp.Compare(a.Value, b.Value); vCmp != 0 {
            return vCmp
        }
        // Secondary sort: Ascending alphabetically by key (name) as a tie-breaker
        return cmp.Compare(a.Key, b.Key)
    })

    return pairs
}

func main() {
    // Initialize the map with the requested values
    scores := map[string]int{
        "Luna":    85,
        "Sofia":   92,
        "Charlie": 96,
        "Bella":   92,
        "Brock":   80,
        "Jolie":   96,
        "Bob":     92,
        "Eve":     92,
    }

    // Sort the map using our function
    sortedPairs := SortMapByValueThenKey(scores)

    // Display the sorted results
    fmt.Println("Sorted by value (score), then by key (name):")
    fmt.Println("--------------------------------------------")
    for _, p := range sortedPairs {
        fmt.Printf("%s: %d\n", p.Key, p.Value)
    }
}


/*
run:

Sorted by value (score), then by key (name):
--------------------------------------------
Brock: 80
Luna: 85
Bella: 92
Bob: 92
Eve: 92
Sofia: 92
Charlie: 96
Jolie: 96

*/

 



answered Oct 23 by avibootz
...