分享
  1. 首页
  2. 文章

Go之sort

ZhDavis · · 1694 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、sort介绍:

Go的pkg提供了一个排序的包sort,用于对slices和用户自定义的类型进行排序操作。原文参考:

Package sort provides primitives for sorting slices and user-defined collections.

https://golang.org/pkg/sort

该包实现了四种基本排序算法:插入排序、归并排序、堆排序和快速排序,但是这四种排序方法是不公开的,它们只被用于 sort 包内部使用。

我们在对数据集合排序时不必考虑应当选择哪一种排序方法,只要实现了 sort.Interface 定义的三个方法,sort 包会根据实际数据自动选择高效的排序算法:

type Interface interface { // Len is the number of elements in the collection. Len() int // 方法1: 获取数据集合长度的 Len() 方法 // Less reports whether the element with // index i should sort before the element with index j. Less(i, j int) bool // 方法2: 比较两个元素大小的 Less() 方法 // Swap swaps the elements with indexes i and j. Swap(i, j int) // 方法3: 和交换两个元素位置的 Swap() 方法}

除此之外,为了方便对常用数据类型的操作,sort 包提供了对[]int 切片、[]float64 切片和[]string 切片完整支持,主要包括下面内容,下面以[]int为例来讲解:(备注:这里的排序是升序)

func Ints(a []int) // 对基本数据类型切片的排序支持
func SearchInts(a []int, x int) int // 基本数据元素查找
func IsSorted(data Interface) bool // 判断基本数据类型切片是否已经排好序
func Reverse(data Interface) Interface // 对排好序的数据集合逆序

二、基本类型int,float64,string的排序

sort实现的是升序操作,对于这三种类型,只需要调用它们的sort方法即可,如果想要进行降序操作,需要主动调用Reverse()方法,例子如下:

package main
import ( "fmt" "sort")
func main() { s1 := []int{-1, 8, 6, 3, 1, 4} // int unsorted sort.Ints(s1) // 升序 fmt.Println(s1) v1 := sort.SearchInts(s1, 6) fmt.Println(v1) sort.Sort(sort.Reverse(sort.IntSlice(s1))) fmt.Println(s1) // 降序
 s2 := []float64{5.9, -1.2, 0.2, -3.7, 2.6} // unsorted sort.Float64s(s2) fmt.Println(s2) // float64 v2 := sort.SearchFloat64s(s2, 0.2) fmt.Println(v2) sort.Sort(sort.Reverse(sort.Float64Slice(s2))) fmt.Println(s2) // 降序
 s3 := []string{"Go", "C++", "Go+", "Alpha", "C", "Delta"} sort.Strings(s3) fmt.Println(s3) v3 := sort. SearchStrings(s3, "C++") fmt.Println(v3) sort.Sort(sort.Reverse(sort.StringSlice(s3))) fmt.Println(s3) // 降序}

执行结果:

[-1 1 3 4 6 8]4[8 6 4 3 1 -1][-3.7 -1.2 0.2 2.6 5.9]2[5.9 2.6 0.2 -1.2 -3.7][Alpha C C++ Delta Go Go+]2[Go+ Go Delta C++ C Alpha]

三、自定义数据结构的排序

对于自定义数据结构的排序,就需要先实现一些方法才行,例如:Len,Less和Swap。原因是如下所示:

“struct 包含多个属性,sort并不知道你想以哪一个属性或哪几个属性作为衡量大小的标准。如果你能帮助程序完成比较,并将结果返回, sort 包内的方法就可以完成排序,判断,查找等。“

1.方法一:

当然,sort也提供了下面几个API来实现数据结构的排序操作,如下所示,我们可以通过这几个API实现数据结构的排序。

func Slice(slice interface{}, less func(i, j int) bool) //The sort is not guaranteed to be stable. For a stable sort, use SliceStable.
func SliceStable(slice interface{}, less func(i, j int) bool)
func Search(n int, f func(int) bool) int

例子如下:

package mainimport ( "fmt" "sort")type Student struct { Name string Grade int}func main() { student := []Student{ {"Go", 7}, {"Alice", 55}, {"Ve", 24}, {"Bob", 75}, } // 1.sort.Slice的使用 sort.Slice(student, func(i, j int) bool { return student[i].Grade < student[j].Grade }) // 按成绩升序排序 fmt.Println("Slice Sort by grade:", student)
 sort.Slice(student, func(i, j int) bool { return student[i].Grade > student[j].Grade }) // 按成绩降序排序 fmt.Println("Slice Sort by grade:", student)
 // 2.sort.SliceStable的使用 sort.SliceStable(student, func(i, j int) bool { return student[i].Grade < student[j].Grade }) // 按成绩升序排序 fmt.Println("SliceStable Sort by grade:", student)
 sort.SliceStable(student, func(i, j int) bool { return student[i].Grade > student[j].Grade }) // 按成绩降序排序 fmt.Println("SliceStable Sort by grade:", student)}

执行结果:

Slice Sort by grade: [{Go 7} {Ve 24} {Alice 55} {Bob 75}]Slice Sort by grade: [{Bob 75} {Alice 55} {Ve 24} {Go 7}]SliceStable Sort by grade: [{Go 7} {Ve 24} {Alice 55} {Bob 75}]SliceStable Sort by grade: [{Bob 75} {Alice 55} {Ve 24} {Go 7}]

2.方法二

模拟IntSlice来实现sort的排序操作,例子如下所示:

package main
import ( "fmt" "sort")
type Student struct { Name string Grade int}type StudentSlice []Student
func (a StudentSlice) Len() int { // 重写 Len() 方法 return len(a)}func (a StudentSlice) Swap(i, j int) { // 重写 Swap() 方法 a[i], a[j] = a[j], a[i]}func (a StudentSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序 return a[j].Grade < a[i].Grade}
func main() { student := []Student{ {"Go", 7}, {"Alice", 55}, {"Ve", 24}, {"Bob", 75}, } sort.Sort(StudentSlice(student)) // 升序 fmt.Println(student) sort.Sort(sort.Reverse(StudentSlice(student)))// 降序 fmt.Println(student)
}

执行结果:

[{Bob 75} {Alice 55} {Ve 24} {Go 7}][{Go 7} {Ve 24} {Alice 55} {Bob 75}]

参考文档:

https://golang.org/pkg/sort
https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter03/03.1.html

https://itimetraveler.github.io/2016/09/07/%E3%80%90Go%E8%AF%AD%E8%A8%80%E3%80%91%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%E6%8E%92%E5%BA%8F%E5%92%8C%20slice%20%E6%8E%92%E5%BA%8F/

原文:https://mp.weixin.qq.com/s/2aZIldsDYTvt1tkdlh4d9g

公众号:灰子学技术


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1694 次点击
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏