Go语言(Golang)sort包的使用

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)
}

猜你喜欢

转载自blog.csdn.net/weixin_42117918/article/details/90738285