一起学go开发:数组排序
数组作为一种常见的数据结构,在实际工作中对数组的排序应用场景非常普遍,无论是php、java、还是今天要说的go,每一种语言都有其特定的实现方式。
我们学习过go语言的标准包和array的用法,我们或许已经知道,可以使用sort.Ints和sort.Slice函数进行排序,但是这个函数只能对纯数字形式的切片进行升序操作。
var a = []int{1, 3, 2, 5, 4}
sort.Ints(a)
fmt.Println(a)
现在有一份学生的成绩单,使用的是数组(或切片)形式,记录了学生的姓名:Name和考试成绩Score,需要对这份成绩单进行排序,该怎么实现呢?先来看看这份成绩单的数据结构:
type Score struct {
name string
score int
}
我们要实现的是将StuScore按照score的大小进行升序、降序的排序。
我们先分析sort.Ints函数是如何实现对纯数字形式的切片进行排序的,Ints函数的源码如下:
// Ints sorts a slice of ints in increasing order.
func Ints(x []int) { Sort(IntSlice(x)) }
初看觉得很简单,对不对?让我们认真的对待这段代码:
x是我们需要进行排序的切片,x先经过IntSlice类型的处理,后由Sort函数处理,注意:Sort的入参是一个Interface。
先来看IntSlice的源码:
// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int
func (x IntSlice) Len() int { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x IntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
从IntSlice源码的注释里,我们得知,IntSlice做的事情是:把Interface的方法加入到x切片。Interface是哪个Interface?Interface有哪几个方法?Interface通常就是本包里定义的Interface,所以我们可以很容易就定位到Interface的源码,如下:
type Interface interface {
Len() int
Less(i int, j int) bool
Swap(i int, j int)
}
这个Interface也就是Sort函数要处理的。
看到这里,我们会有一个疑问:为什么x不直接交给Sort处理,而要先经过IntSlice处理再由Sort处理?
这样做的目的是,让x具备Len、Less、Swap这三个接口定义的方法签名,以便于交给Sort进行排序,未实现这三个方法签名的切片不具备排序的能力。
既然知道了切片实现排序的基本原理,把我们的成绩单转换为可排序的切片,就可以实现对成绩单进行升序、降序的排序操作了。
实现步骤:
第一步:定义成绩单模型Score,并为成绩单实现Len、Less、Swap这三个方法
// Desc false默认升序,true为降序
var Desc bool
type Score struct {
name string
score int
}
type Scores []Score
func (s Scores) Len() int {
return len(s)
}
func (s Scores) Less(i, j int) bool {
if Desc {
return s[i].score > s[j].score
}
return s[i].score < s[j].score
}
func (s Scores) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
第二步:模拟学生成绩单
// SchoolReport 成绩单
func SchoolReport() {
scores := Scores{
{"alan", 95},
{"hikerell", 91},
{"acmfly", 96},
{"leao", 90},
}
fmt.Println("Default:\n\t", scores)
sort.Sort(scores)
fmt.Println("IS Sorted?\n\t", sort.IsSorted(scores))
fmt.Println("Sorted:\n\t", scores)
}
第三步:分别调用升序函数、降序函数,实现对成绩单的排序操作
student.SchoolReport() student.Desc = true student.SchoolReport()
除了以上的排序方式外,还可以使用sort.Slice实现排序,代码如下:
var desc bool
people :=[]struct{
Name string
Age int
}{
{"Gopher", 7},
{"Alice", 55},
{"Vera", 24},
{"Bob", 75},
}
desc = true
sort.Slice(people, func(i, j int) bool {
if desc {
return people[i].Age > people[j].Age
}
return people[i].Age < people[j].Age
})
fmt.Println("Sort by age:\n", people)

浙公网安备 33010602011771号