import "sort"
sort包提供了排序切片和用户自定义数据集的函数。
通过使用golang提供的包sort,可以快速实现复杂结构的数据排序。
如果要使用sort,需要实现sort下 Interface对应的方法:Len()、Less()、Swap()3个方法。
package sort
// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
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)
}
示例:
示例1:简单排序
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
//重写 fmt包的String方法,按照自定义方式输出
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
// Persons implements sort.Interface for []Person based on
// the Age field.
type Persons []Person
func (a Persons) Len() int { return len(a) }
func (a Persons) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a Persons) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
people := []Person{
{"张三", 23},
{"李四", 24},
{"王五", 20},
{"赵六", 19},
}
fmt.Println("原始数据:",people)
sort.Sort(Persons(people))
fmt.Println("排序之后的数据:",people)
}
示例2:对同一产品,依据不同属性进行排序
package main
import (
"fmt"
"sort"
)
type Grams int
//重写 fmt包的String方法,按照自定义方式输出
func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }
type Fruit struct {
Name string
Weight Grams
}
type Fruits []*Fruit
//公共的方法
func (s Fruits) Len() int { return len(s) }
func (s Fruits) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// ByName继承 Fruits
type ByName struct{ Fruits }
//ByName特有的方法,依据名称排序
func (s ByName) Less(i, j int) bool { return s.Fruits[i].Name < s.Fruits[j].Name }
// ByWeight 继承Fruit
type ByWeight struct{ Fruits }
//ByWeight特有的方法,依据重量排序
func (s ByWeight) Less(i, j int) bool { return s.Fruits[i].Weight < s.Fruits[j].Weight }
func main() {
s := []*Fruit{
{"苹果", 240},
{"香蕉", 190},
{"梨子", 194},
{"石榴", 331},
{"葡萄", 32},
{"西瓜", 10162},
}
sort.Sort(ByWeight{s})
fmt.Println("依据重量排序:")
printFruits(s)
sort.Sort(ByName{s})
fmt.Println("依据名称排序:")
printFruits(s)
}
func printFruits(s []*Fruit) {
for _, o := range s {
fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
}
}
示例3:
package main
import (
"fmt"
"sort"
)
// A Change is a record of source code changes, recording user, language, and delta size.
type Change struct {
user string
language string
lines int
}
type lessFunc func(p1, p2 *Change) bool
// multiSorter implements the Sort interface, sorting the changes within.
type multiSorter struct {
changes []Change //排序的数据
less []lessFunc //排序的标准(函数)
}
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
ms.changes = changes
sort.Sort(ms)
}
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter { //可变参数,实现多个标准(函数)设定的排序
return &multiSorter{
less: less,
}
}
// Len is part of sort.Interface.
func (ms *multiSorter) Len() int {
return len(ms.changes)
}
// Swap is part of sort.Interface.
func (ms *multiSorter) Swap(i, j int) {
ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}
// Less is part of sort.Interface. It is implemented by looping along the
// less functions until it finds a comparison that is either Less or
// !Less. Note that it can call the less functions twice per call. We
// could change the functions to return -1, 0, 1 and reduce the
// number of calls for greater efficiency: an exercise for the reader.
func (ms *multiSorter) Less(i, j int) bool {
p, q := &ms.changes[i], &ms.changes[j]
// Try all but the last comparison.
var k int
//如果有多个lessFunc
for k = 0; k < len(ms.less)-1; k++ {
less := ms.less[k]
switch {
case less(p, q):
// p < q, so we have a decision.
return true
case less(q, p):
// p > q, so we have a decision.
return false
}
// p == q; try the next comparison.
}
// All comparisons to here said "equal", so just return whatever
// the final comparison reports.
return ms.less[k](p, q)
}
//定义需要排序的数据
var changes = []Change{
{"gri", "Go", 100},
{"ken", "C", 150},
{"glenda", "Go", 260},
{"rsc", "Go", 200},
{"r", "Go", 100},
{"ken", "Go", 180},
{"dmr", "C", 100},
{"r", "C", 150},
{"gri", "Smalltalk", 80},
}
// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func main() {
// Closures that order the Change structure.
user := func(c1, c2 *Change) bool {
return c1.user < c2.user
}
language := func(c1, c2 *Change) bool {
return c1.language < c2.language
}
increasingLines := func(c1, c2 *Change) bool {
return c1.lines < c2.lines
}
decreasingLines := func(c1, c2 *Change) bool {
return c1.lines > c2.lines // Note: > orders downwards.
}
fmt.Println("=================原始数据=================================")
fmt.Println(changes)
// Simple use: Sort by user.
fmt.Println("=====================通过user简单排序=======================")
OrderedBy(user).Sort(changes)
fmt.Println("By user:", changes)
// More examples.
fmt.Println("================通过user,分数升序排列(user优先)==============")
OrderedBy(user, increasingLines).Sort(changes)
fmt.Println("By user,<lines:", changes)
fmt.Println("================通过user,分数降序排列(user优先)===========")
OrderedBy(user, decreasingLines).Sort(changes)
fmt.Println("By user,>lines:", changes)
fmt.Println("=============通过language,分数升序排列(language优先)===========")
OrderedBy(language, increasingLines).Sort(changes)
fmt.Println("By language,<lines:", changes)
fmt.Println("======通过language,分数升序排列、user排序(优先级:language、分数、user)=========")
OrderedBy(language, increasingLines, user).Sort(changes)
fmt.Println("By language,<lines,user:", changes)
}