Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How one can do case insensitive sorting using sort.Strings() in Golang?

Tags:

sorting

go

Is there any way to pass the custom function in the sort.Strings() to do the case-insensitive sorting on the list of strings?

data := []string{"A", "b", "D", "c"}

The output should be: A, b, c, D

The equivalent of the above requirement in Python is like :

li = sorted(data, key=lambda s: s.lower())

Do we have something like that in golang?

like image 518
CodeQuestor Avatar asked Dec 07 '22 14:12

CodeQuestor


1 Answers

The translation of the Python code to Go is:

sort.Slice(data, func(i, j int) bool { return strings.ToLower(data[i]) < strings.ToLower(data[j]) })

Run it on the Go Playground.

This approach, like the Python code in the question, can allocate two strings for each comparison. The allocations are probably OK for the example in the question, but can be a problem in other scenarios.

To avoid allocations, compare the strings rune by rune:

func lessLower(sa, sb string) bool {
    for {
        rb, nb := utf8.DecodeRuneInString(sb)
        if nb == 0 {
            // The number of runes in sa is greater than or 
            // equal to the number of runes in sb. It follows
            // that sa is not less than sb.
            return false
        }

        ra, na := utf8.DecodeRuneInString(sa)
        if na == 0 {
            // The number of runes in sa is less than the
            // number of runes in sb. It follows that sa
            // is less than sb.
            return true
        }

        rb = unicode.ToLower(rb)
        ra = unicode.ToLower(ra)

        if ra != rb {
            return ra < rb
        }

        // Trim rune from the beginning of each string.
        sa = sa[na:]
        sb = sb[nb:]
    }
}
⋮
sort.Slice(data, func(i, j int) bool { return lessLower(data[i], data[j]) })

Run it on the Go Playground.

Take a look at the collate package if you need to sort by language or culture specific sort orders.

like image 181
Bayta Darell Avatar answered Dec 29 '22 00:12

Bayta Darell