In Golang, how can I sort a list of strings alphabetically without completely ignoring case?

Koala3 picture Koala3 · Jan 29, 2016 · Viewed 12.1k times · Source

I want the strings to be sorted alphabetically with control over whether "A" comes before "a".

In the Less() function using strings.ToLower() doesn't achieve this. Sometimes "A" comes before "a", and sometimes after.

Answer

JimB picture JimB · Jan 29, 2016

instead of comparing the entire string using strings.ToLower, compare the individual runes.

https://play.golang.org/p/RUMlmrb7C3g

type ByCase []string

func (s ByCase) Len() int      { return len(s) }
func (s ByCase) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByCase) Less(i, j int) bool {
    iRunes := []rune(s[i])
    jRunes := []rune(s[j])

    max := len(iRunes)
    if max > len(jRunes) {
        max = len(jRunes)
    }

    for idx := 0; idx < max; idx++ {
        ir := iRunes[idx]
        jr := jRunes[idx]

        lir := unicode.ToLower(ir)
        ljr := unicode.ToLower(jr)

        if lir != ljr {
            return lir < ljr
        }

        // the lowercase runes are the same, so compare the original
        if ir != jr {
            return ir < jr
        }
    }

    // If the strings are the same up to the length of the shortest string, 
    // the shorter string comes first
    return len(iRunes) < len(jRunes)
}