SoFunction
Updated on 2025-03-05

Golang's solution to sort custom types

Preface

Go language supports us to customize types. In actual projects, we often need to sort according to a field of a structure type. I didn't know how to solve this problem before. Later, I searched for related problems online and found some good solutions. Here I will give a summary.

Since the golang's sort package itself provides corresponding functions, there is no need to make a wheel repeatedly, let's see how to use the sort package to implement it.

Sort brief discussion

The sort package of the sort algorithm is also implemented in golang. The sort package implements four basic sort algorithms internally: insertion sort (insertionSort), merge sort (symMerge), heap sort (heapSort) and quickSort; the sort package will automatically select the optimal sort algorithm based on actual data.

So when writing code, we only need to consider implementationThis type is OK.

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 := ()
 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 internally implemented sorting algorithms// Insert sortfunc insertionSort(data Interface, a, b int)
// Heap sortingfunc heapSort(data Interface, a, b int)
// Quick sortfunc quickSort(data Interface, a, b, maxDepth int)
// Orderingfunc symMerge(data Interface, a, m, b int)

So call()To implement custom type sorting, we only need to implement three methods in the Interface interface type.

First look at the sort package itself[]int How to sort types

// First define an alias of []int type IntSlicetype IntSlice []int
// Get the length of this slicefunc (p IntSlice) Len() int   { return len(p) }
// Compare the size of two elements ascending orderfunc (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
// Exchange datafunc (p IntSlice) Swap(i, j int)  { p[i], p[j] = p[j], p[i] }
// () Internal call Sort() method to achieve sorting// Note: You must first convert []int to IntSlice type because this type implements three methods of Interfacefunc Ints(a []int) { Sort(IntSlice(a)) }

Let's 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 slicefunc (p Persons) Len() int { return len(p) }
// Sort by descending age of elements (write here according to your own business logic)func (p Persons) Less(i, j int) bool {
 return p[i].Age > p[j].Age
}
// Exchange datafunc (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,
 },
 }
 ("Before sorting")
 for _, person := range persons {
 (, ":", )
 }
 (persons)
 ("After sorting")
 for _, person := range persons {
 (, ":", )
 }
}

Actually, generallyLen()andSwap() There are basically no changes, only elements are involvedLess() The method will change.

What should we do when we sort multiple fields in a certain structure? Do we write these three methods for each sorting one? Of course not. We can use nested structures to solve this problem. Because nested structures can inherit all properties and methods of the parent structure

For example, if I want to sort the Name field and Age of Person above, we can use nested structures to improve it.

package main
import (
 "fmt"
 "sort"
)
type Person struct {
 Name string
 Age int
}
type Persons []Person
//The Len() method and Swap() method do not need to be changed// Get the length of this slicefunc (p Persons) Len() int { return len(p) }
// Exchange datafunc (p Persons) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Nested structure will inherit all properties and methods of Person// So So the equivalent of SortByName also implements the Len() and Swap() methodstype 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([i].Name) > len([j].Name)
}
type SortByAge struct{ Persons }
// Sort by descending age of elements (write here according to your own business logic)func (p SortByAge) Less(i, j int) bool {
 return [i].Age > [j].Age
}
func main() {
 persons := Persons{
 {
 Name: "test123",
 Age: 20,
 },
 {
 Name: "test1",
 Age: 22,
 },
 {
 Name: "test12",
 Age: 21,
 },
 }
 ("Before sorting")
 for _, person := range persons {
 (, ":", )
 }
 (SortByName{persons})
 ("After sorting")
 for _, person := range persons {
 (, ":", )
 }
}

Summarize

The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support.