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.
7 Answers
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.
You're looking for sort.Reverse. That will let you say:
sort.Sort(sort.Reverse(fooAscending(s))) 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:
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.
Just wrap the type of a basic type using an appropriate Interface method provider, e.g. StringSlice, IntSlice, or Float64Slice, and sort.
The slice is sorted in-place, and hence does not return a copy of the sorted slice.
you can import the "sort" package from standard library of golang . then you can use either "Slice" or "SliceStable" function to sort your slice. it is recommended to use the second one like this :
sort.SliceStable(yourSlice , anonnymousFunction)example : package main
import ( "fmt" "sort"
)
func main() { a := []int{4,5,9,6,8,3,5,7,99,58,1} sort.SliceStable(a, func(i,j int )bool{ //i,j are represented for two value of the slice . return a[i] < a[j] }) fmt.Println(a)
} The accepted answer is good, but I disagree with their suggestion on descending:
a[i] > a[j]With sort.Slice, the provided function is supposed to represent an
implementation of "less than":
func Slice(x interface{}, less func(i, j int) bool)
Slicesorts the slicexgiven the providedlessfunction. It panics ifxis not a slice.
So writing a "greater than" function, isn't really true to the given description. Better would be to reverse the indexes:
package main
import ( "fmt" "sort"
)
func main() { a := []int{5, 3, 4, 7, 8, 9} sort.Slice(a, func(i, j int) bool { return a[j] < a[i] }) fmt.Println(a) // [9 8 7 5 4 3]
}both should return the same result, but I think one is more idiomatic.
0var names = []string{"b", "a", "e", "c", "d"}
sort.Strings(names)
fmt.Println("Sorted in alphabetical order", names)
sort.Sort(sort.Reverse(sort.StringSlice(names)))
fmt.Println("Sorted in reverse order", names)link for The Go Playgound
if for any reasons you can't or don't want to use the sort package, the following will implement a bubble sort type of sorting (it accepts an int64 slice and returns an int64 slice):
func sortSlice ( S []int64 ) []int64 { // sort using bubblesort, comparing each pairs of numbers and ensuring that left is lower than right for i := len(S); i > 0 ; i-- { for j := 1; j < i; j++ { if S[j-1] > S[j] { // swap intermediate := S[j] S[j] = S[j-1] S[j-1] = intermediate } } } return S
}