[轉]Golang’s solution to sorting custom types
原文:https://developpaper.com/golangs-solution-to-sorting-custom-types/
--------------------------------
Preface
Go language supports our custom types. In actual projects, we often need to sort according to a certain field of a structure type. I didn’t know how to solve this problem before. Later, I searched the Internet for related problems and found some good solutions. Here is a summary.
Because the sort package ofgolangprovides corresponding functions, we don’t need to build a wheel repeatedly. Let’s see how to use the sort package to realize it.
On sort package
The sort package of sorting algorithm is also implemented in golang. The sort package internally implements four basic sorting algorithms: insertion sort, symmerge, heap sort and quick sort. The sort package automatically selects the optimal sorting algorithm according to the actual data.
So when we write code, we only need to consider the implementationsort.Interface
This type is fine.
Take a rough 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) } //Four sorting algorithms implemented internally //Insert sort func insertionSort(data Interface, a, b int) // heap sort func heapSort(data Interface, a, b int) //Quick sort func quickSort(data Interface, a, b, maxDepth int) //Merge sort func symMerge(data Interface, a, m, b int)
So callsort.Sort()
To implement custom type sorting, we only need our type to implement three methods in the interface interface type.
First look at the sort package itself[]int
How to sort types
//First, an alias of type [] int intslice is defined type IntSlice []int //Get the length of this slice func (p IntSlice) Len() int { return len(p) } //Compare two element sizes in ascending order func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] } //Exchange data func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } //Sort. Ints() calls the sort() method internally to implement sorting //Note that we need to convert [] int to intslice type first, because this type implements three methods of interface func Ints(a []int) { Sort(IntSlice(a)) }
According to huluduapiao, we can sort the custom structure types in descending order
package main import ( "fmt" "sort" ) type Person struct { Name string Age int } type Persons []Person //Get the length of this slice func (p Persons) Len() int { return len(p) } //Sort by the age of the element in descending order (write here according to your own business logic) func (p Persons) Less(i, j int) bool { 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 ("before sorting") for _, person := range persons { fmt.Println(person.Name, ":", person.Age) } sort.Sort(persons) Fmt.println ("after sorting") for _, person := range persons { fmt.Println(person.Name, ":", person.Age) } }
In fact, generalLen()
andSwap()
Basically no change, only involving element comparisonLess()
The approach will change.
What should we do when sorting multiple fields in a certain structure? Do we write down these three methods for each sorting? Of course not. We can use nested structures to solve this problem. Because nested structures can inherit all the properties and methods of the parent structure
For example, if I want to sort the name field and age of the person above, we can use nested structure to improve it.
package main import ( "fmt" "sort" ) type Person struct { Name string Age int } type Persons []Person //The len () and swap () methods do not change //Get the length of this slice func (p Persons) Len() int { return len(p) } //Exchange data func (p Persons) Swap(i, j int) { p[i], p[j] = p[j], p[i] } //Nested structures inherit all properties and methods of person //So sortByName also implements len() and swap() methods type SortByName struct{ Persons } //Sort by the name length of the element in descending order (write here according to your own 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 element in descending order (write here according to your own business logic) func (p SortByAge) Less(i, j int) bool { return p.Persons[i].Age > p.Persons[j].Age } func main() { persons := Persons{ { Name: "test123", Age: 20, }, { Name: "test1", Age: 22, }, { Name: "test12", Age: 21, }, } Fmt.println ("before sorting") for _, person := range persons { fmt.Println(person.Name, ":", person.Age) } sort.Sort(SortByName{persons}) Fmt.println ("after sorting") for _, person := range persons { fmt.Println(person.Name, ":", person.Age) } }
summary
The above is the whole content of this article. I hope that the content of this article has a certain reference learning value for everyone’s study or work. If you have any questions, you can leave a message and exchange. Thank you for your support for developepaar.