在程序开发中,不可避免的需要给数据集进行排序,如果在语言级别不提供支持的话,我们则需要自己写算法进行数据的处理,麻烦还不一定高效。
幸好Golang在标准包中,官方有提供sort包中Sort()函数提供排序功能。并且天然支持[]int,[]float64,[]string切片的排序查找功能,并且也能够实现对自定义类型集合的排序。
下面我们先来看下golang中Sort函数的结构是什么样的。
func Sort(data Interface) {
n := data.Len()
quickSort(data, 0, n, maxDepth(n))
}
可以看到,该函数接收的唯一的参数就是待排序集合,该集合应是一个Interface,而我们如果需要让自定义类型的集合能够被排序,则需要实现该interface以保证类型一致。该接口中有三个方法:
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)
}
数据集合实现了这三个方法后,就可以使用该包的Sort()函数进行排序。
1.1让我们来看一个以学生年龄排序的小案例:
type Stu []student
func main() {
var students = make(Stu, 0)
for i := 0; i < 10; i++ {
stu := student{
name: strconv.Itoa(i) + "~~",
age: i,
}
students = append(students, stu)
}
for _, item := range students {
fmt.Println(item.name, "--", item.age)
}
sort.Sort(students)
fmt.Println("is sorted? ", sort.IsSorted(students)) //可以检测是否已经排序
for _, item := range students {
fmt.Println(item.name, "--", item.age)
}
}
func (s Stu) Len() int { //返回集合的长度
return len(s)
}
func (s Stu) Less(i, j int) bool { //用来决定是升序还是降序
return s[i].age > s[j].age
}
func (s Stu) Swap(i, j int) { //改变数据在集合中的位置
s[i], s[j] = s[j], s[i]
}
type student struct {
name string
age int
}
在Less方法中,我使用的是int类型的年龄来进行降序排列的,如果需要升序只需要变成 < 号即可:
func (s Stu) Less(i, j int) bool {
return s[i].age < s[j].age
}
1.2最后再来个基本int型的使用案例
在sort包中,给[]int排序的方法是IntSlice,结构如下:
type IntSlice []int
func (p IntSlice) Len() int { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }
可以看到,该[]int也实现了Sort函数中的接口,并且有一个Sort()方法,所以我们可以这样使用:
var nums = []int{1, 3, 2, 5, 3, 65, 3}
sort.IntSlice(nums).Sort()
如果我们不想这么麻烦,sort包为我们提供了一个Ints方法,调用该方法可以直接排序:
var nums = []int{1, 3, 2, 5, 3, 65, 3}
sort.Ints(nums)
fmt.Println(nums)
输出结果:
[1 2 3 3 3 5 65]
如果需要改变排序方式的话,包中同样有提供一个Reverse方法:
func Reverse(data Interface) Interface {
return &reverse{data}
}
我们看到,Reverse函数跟Sort函数接收同样的方法,所以我们的排序时需要使用实现了那三个方法的IntSlice方法,使用方式:
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
剧终!
有疑问加站长微信联系(非本文作者)