sorting – golang sort slice ascending or descending-ThrowExceptions

Exception or error:

I need to sort a slice of a type that is coming from a 3rdparty package. Based on some condition the order must be ascending or descending.

The solution I come up with is:

type fooAscending []foo

func (v fooAscending) Len() int           { return len(v) }
func (v fooAscending) Swap(i, j int)      { v[i], v[j] = v[j], v[i] }
func (v fooAscending) Less(i, j int) bool { return v[i].Amount < v[j].Amount }

type fooDescending []foo

func (v fooDescending) Len() int           { return len(v) }
func (v fooDescending) Swap(i, j int)      { v[i], v[j] = v[j], v[i] }
func (v fooDescending) Less(i, j int) bool { return v[i].Amount > v[j].Amount }

if someCondition {
    sort.Sort(fooAscending(array))
} else {
    sort.Sort(fooDescending(array))
}

Is there a better way to do this. 13 lines of code for this task and most of it is duplicated, seems a bit too much.

How to solve:

As of Go 1.8, there is an easier way to sort a slice that does not require you to define new types. You simply pass an anonymous function to the sort.Slice function.

a := []int{5, 3, 4, 7, 8, 9}
sort.Slice(a, func(i, j int) bool {
    return a[i] < a[j]
})
for _, v := range a {
    fmt.Println(v)
}

This will sort in ascending order, if you want the opposite, simply write a[i] > a[j] in the anonymous function.

Answer:

You’re looking for sort.Reverse. That will let you say:

sort.Sort(sort.Reverse(fooAscending(s)))

Answer:

My answer below is based on the assumption that the slice that you are receiving from a third party package is of a basic Go type.

To sort slices of basic types, use the sort package utilities. Here is an example that sorts a slice of string and a slice of int.

package main

import (
    "fmt"
    "sort"
)

func main() {
    sl := []string{"mumbai", "london", "tokyo", "seattle"}
    sort.Sort(sort.StringSlice(sl))
    fmt.Println(sl)

    intSlice := []int{3,5,6,4,2,293,-34}
    sort.Sort(sort.IntSlice(intSlice))
    fmt.Println(intSlice)
}

The output of the above is:

[london mumbai seattle tokyo]
[-34 2 3 4 5 6 293]

Go to Go Playground here to try it out yourself.

A few things of note:

  1. Sorting basic Go types does not require implementing functions such as Len() that belong to sort.Interface. You need to take that route only for composite types.

  2. Just wrap the type of a basic type using an appropriate Interface method provider, e.g. StringSlice, IntSlice, or Float64Slice, and sort.

  3. The slice is sorted in-place, and hence does not return a copy of the sorted slice.

Leave a Reply

Your email address will not be published. Required fields are marked *