This is a creation in Article, where the information may have evolved or changed.
Golang to sort custom types
In a real project, we often need to sort by a field of a struct type. Before encountering this problem do not know how to solve, later in the online search for related issues, found some good solution, here reference, do a summary of it.
Since the Golang sort package itself provides the appropriate functionality, there is no need to reinvent the wheel to see how to use the sort package to achieve it.
A brief discussion on sort package
The sort package internally implements four basic sorting algorithms: Insert sort (insertionsort), merge sort (symmerge), heap sort (heapsort), and quick sort (quickSort); sort The package will automatically select the optimal sorting algorithm based on the actual data. So we just need to think about implementing sort when we write code. This type of Interface is available.
A cursory look at the sort package
func Sort(data Interface) { // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached. n := data.Len() maxDepth := 0 for i := n; i > 0; i >>= 1 { maxDepth++ } maxDepth *= 2 quickSort(data, 0, n, maxDepth)}type Interface interface { // Len is the number of elements in the collection. Len() int // Less reports whether the element with // index i should sort before the element with index j. Less(i, j int) bool // Swap swaps the elements with indexes i and j. Swap(i, j int)}// 内部实现的四种排序算法// 插入排序func insertionSort(data Interface, a, b int)// 堆排序func heapSort(data Interface, a, b int)// 快速排序func quickSort(data Interface, a, b, maxDepth int)// 归并排序func symMerge(data Interface, a, m, b int)
So to call sort. Sort () to implement a custom type sort, only requires our type to implement the three methods in the Interface interface type.
Let's take a look at the sort package itself for [how]int types are sorted
// 首先定义了一个[]int类型的别名IntSlice type IntSlice []int// 获取此 slice 的长度func (p IntSlice) Len() int { return len(p) }// 比较两个元素大小 升序func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }// 交换数据func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }// sort.Ints()内部调用Sort() 方法实现排序// 注意 要先将[]int 转换为 IntSlice类型 因为此类型才实现了Interface的三个方法 func Ints(a []int) { Sort(IntSlice(a)) }
Divert us to sort the custom struct types in descending order
Package Mainimport ("FMT", "sort") type person struct {Name string age int}type Persons []person// Gets the length of this slice func (P Persons) len () int {return Len (p)}//sorted according to the age of the elements (written here according to your business logic) func (P Persons) Less (i, J int) Bo OL {return p[i]. Age > P[j]. age}//Exchange data func (P Persons) Swap (i, J int) {P[i], p[j] = P[j], P[i]}func main () {Persons: = persons{{ Name: "Test1", Age:20,}, {Name: "Test2", Age:22,}, {Name: "Test3", Age:21,},} FMT. Println ("Pre-sort") for _, Person: = Range Persons {FMT. Println (person. Name, ":", person. Age)} sort. Sort (persons) FMT. Println ("Post-order") for _, Person: = Range Persons {FMT. Println (person. Name, ":", person. Age)}}
In fact, the General Len () and Swap () do not change basically, only the less () method involving the comparison of elements will change.
What do we do when we sort multiple fields in a struct, or do we write down these three methods for each sort of thing? We can use nested constructs to solve this problem. because a nested struct can inherit all the properties and methods of the parent struct's body
For example, if I want to sort the Name field of the person above and the age pair, we can use the nested structure to improve it.
Package Mainimport ("FMT", "sort") type person struct {Name string age int}type Persons []person//Len () method and SW The AP () method does not change//Gets the length of this slice func (P Persons) len () int {return Len (p)}//interchange data func (P Persons) Swap (i, J int) {P[i], p[j] = P[j], p[i]}//the nested struct inherits all the properties and methods of the person//so the equivalent of Sortbyname also implements the Len () and Swap () methods type Sortbyname struct{Persons}//according to The name length of the element is sorted in descending order (written here according to your business logic) func (P sortbyname) Less (i, J int) bool {return Len (P.persons[i]. Name) > Len (p.persons[j]. Name)}type sortbyage struct{Persons}//Sort by the age of the elements (write in your own business logic here) func (P sortbyage) Less (i, J int) bool {return p.pe Rsons[i]. Age > P.persons[j]. Age}func Main () {persons: = persons{{Name: "test123", Age:20,}, { Name: "Test1", Age:22,}, {Name: "test12", Age:21,}, } FMT. Println ("Pre-sort") for _, Person: = Range Persons {FMT. Println (person. Name, ":", person. Age)} Sort. Sort (Sortbyname{persons}) fmt. Println ("Post-order") for _, Person: = Range Persons {FMT. Println (person. Name, ":", person. Age)}}