How to rank elements of a slice in Go

1 Answer

0 votes
package main

import (
    "fmt"
    "sort"
)

/*
    FUNCTION: getRanks
    -------------------
    This function takes a slice of numbers and returns a slice of ranks.

    Ranking rules used (Competition Ranking):
    -----------------------------------------
    - Highest value gets rank 1
    - Equal values get the same rank
    - Next rank increases by the number of equal values

    Example:
        Values: 88, 4, 19, 4, 1, 31, 14, 1, 93, 17
        Ranks:   2, 7,  4, 7, 9,  3,  6, 9,  1,  5

    Steps:
    1. Make a sorted copy of the slice (descending)
    2. Assign ranks to each unique value
    3. Build a rank slice matching the original order
*/
func getRanks(slice []int) []int {

    // Step 1: Create a sorted copy (descending)
    sorted := make([]int, len(slice))
    copy(sorted, slice)
    sort.Slice(sorted, func(i, j int) bool {
        return sorted[i] > sorted[j] // descending
    })

    // Step 2: Map each unique value to its rank
    rankMap := make(map[int]int)
    rank := 1

    for _, value := range sorted {
        // Assign rank only once per unique value
        if _, exists := rankMap[value]; !exists {
            rankMap[value] = rank
        }
        rank++ // next rank position
    }

    // Step 3: Build ranking slice in original order
    ranks := make([]int, len(slice))
    for i, value := range slice {
        ranks[i] = rankMap[value]
    }

    return ranks
}

/*
    FUNCTION: printRanking
    -----------------------
    Prints the original slice and its ranking.
*/
func printRanking(slice []int, ranks []int) {
    fmt.Print("Original slice: [ ")
    for _, v := range slice {
        fmt.Print(v, " ")
    }
    fmt.Println("]")

    fmt.Print("Ranking slice : [ ")
    for _, r := range ranks {
        fmt.Print(r, " ")
    }
    fmt.Println("]")
}

// MAIN PROGRAM
// ---------------------------------------------
func main() {

    // slice
    slice := []int{88, 4, 19, 4, 1, 31, 14, 1, 93, 17}

    // Compute ranks
    rankingSlice := getRanks(slice)

    printRanking(slice, rankingSlice)
}



/*
run:

Original slice: [ 88 4 19 4 1 31 14 1 93 17 ]
Ranking slice : [ 2 7 4 7 9 3 6 9 1 5 ]

*/

 



answered 1 day ago by avibootz
...