1. 程式人生 > 其它 >[轉]Golang’s solution to sorting custom types

[轉]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.InterfaceThis 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[]intHow 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.