对于 Go 语言来说,主要对两种类型的数据进行排序(一般都是对于切片类型数据排序):① 切片 ② 结构体,切片一般对应基本的数据类型,例如 int,float 类型的数字,string 字符串等基本数据类型的切片;对于结构体的排序,类似于 python 列表嵌套元组(或者是列表嵌套列表),例如对于 python 中的列表 a:a = [(1,2,4),(3,4,2),(5,2,7)],python 对列表中的元组排序可以使用 python 中的 sort 方法并且利用 lambda 表达式自定义按照元组的第几个元素进行排序:a.sort(key=lambda x: x[1]),而 Go 语言的结构体排序类似于 python 列表嵌套元组然后进行排序,Go 语言中一般使用切片来嵌套结构体进行排序,嵌套结构体之后就可以实现比较复杂的数据结构的排序,下面是一些常见排序方法:
1. 对 int 类型的切片从小到大排序可以使用 sort.Ints 函数,这个函数默认是从小到大进行排序,如果需要从大到小排序第一种方法可以使用 sort.Sort(sort.Reverse(sort.IntSlice(slice)))进行排序,其中 slice 为切片;第二种方法调用 sort.Sort() 函数,需要实现 Sort 接口中的 Len(),Less(),Swap() 方法,其中排序的核心是 Less 函数,需要在 Less 函数中定义排序的规则也即定义按照什么规则进行排序;第三种方法可以使用 sort.Slice() 函数进行排序,此时需要传递一个匿名函数,这个函数需要实现类似于 Sort 接口中的 Less 函数的功能,也即定义排序的规则,而对于浮点数排序可以使用 Float64s 函数:
package main
import (
"fmt"
"sort"
)
type hp []int
// 下面三个方法属于Sort接口中的方法, 任何实现了Sort接口中的方法都可以自定义排序
func (p hp) Len() int { return len(p) }
// 核心是Less方法, 定义比较规则
func (p hp) Less(i, j int) bool { return p[i] > p[j] }
func (p hp) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func main() {
a := []int{1, 4, 23, 5, 6, 19, 34}
// 1. 利用Ints函数对int类型的整数从小到大进行排序
fmt.Println("Ints函数对int类型切片升序排序: ")
sort.Ints(a)
fmt.Println(a)
// 2. 从大到小排序
fmt.Println("从大到小排序: ")
b := []int{10, 2, 5, 12, 4, 35}
// Sort函数的参数为一个interface接口, sort.Reverse函数返回的就是一个接口
sort.Sort(sort.Reverse(sort.IntSlice(b)))
fmt.Println(b)
// 3. 使用sort.Sort()函数对切片进行排序, 函数的参数为接口类型(可以参照官方文档中的例子进行修改)
c := []int{1, 4, 2, 5, 8}
// 实现Sort接口中的三个方法进行排序
fmt.Println("实现Sort接口中的三个方法进行排序")
sort.Sort(hp(c))
fmt.Println(c)
// 4. 使用Slice函数对切片进行排序, 第一个参数为待排序的切片类型, 并且传递一个匿名函数实现Sort接口中Less函数的相同要求
d := []int{1, 6, 3, 4, 19, 34, 5}
sort.Slice(d, func(i, j int) bool {
// 自定义排序的规则, 大于表示从大到小进行排序
return d[i] > d[j]
})
fmt.Print(d)
}
2. 对 string 字符串类型的切片进行排序,与 int 类型的切片排序是类似的:
package main
import (
"fmt"
"sort"
)
func main() {
s := []string{"Go", "Bravo", "Gopher", "Alpha", "Grin", "Delta"}
sort.Strings(s)
fmt.Println(s)
// 从大到小进行排序
sort.Sort(sort.Reverse(sort.StringSlice(s)))
fmt.Println(s)
}
3. 对结构体进行排序,可以使用 sort.Sort() 函数对结构体列表进行排序,使用 Sort 函数需要实现 Sort 接口中的三个方法,下面是对 nums 中数字的出现次数进行计数,并且按照出现次数从大到小排序输出结果:
package main
import (
"fmt"
"sort"
)
// 使用type关键字定义一个结构体和结构体切片mp, key为数字, value为数字的出现次数
type pair struct{ key, value int }
// 切片中的每一个元素都是一个结构体
type mp []pair
// 实现Sort接口中的三个方法
func (m mp) Len() int { return len(m) }
func (m mp) Less(i, j int) bool { return m[i].value > m[j].value }
func (m mp) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func main() {
nums := []int{1, 1, 3, 3, 3, 3, 2, 7, 7, 8, 8, 8, 9}
// 统计每一个数的出现次数并且按照出现次数由大到小进行排序
count := make(map[int]int)
for i := 0; i < len(nums); i++ {
count[nums[i]] += 1
}
// 声明一个结构体切片a
var a []pair
// 遍历map, 将键值对存储到结构体切片中
for k, v := range count {
a = append(a, pair{k, v})
}
// 使用sort.Sort方法进行排序
sort.Sort(mp(a))
fmt.Println(a)
}
第二种对结构体列表排序的方法可以使用 sort.Slice() 函数,类似于对 int 类型的切片进行排序,需要传递一个匿名函数,函数中实现类似于 Sort 接口中 Less 方法的功能,这个函数比较方便的是可以实现对二维切片进行排序:
package main
import (
"fmt"
"sort"
)
type pair struct{ key, value int }
func main() {
nums := []int{1, 1, 3, 3, 3, 3, 2, 7, 7, 8, 8, 8, 9}
count := make(map[int]int)
for i := 0; i < len(nums); i++ {
count[nums[i]] += 1
}
var a []pair
for k, v := range count {
a = append(a, pair{k, v})
}
// 使用sort.Slice()函数比较方便的一点是代码比较短, 写起来比较方便
sort.Slice(a, func(i, j int) bool {
return a[i].value > a[j].value
})
fmt.Println(a)
b := [][]int{{1, 2}, {0, 3}, {-1, 5}, {-1, 4}}
sort.Slice(b, func(i, j int) bool {
return b[i][0] <= b[i][1]
})
fmt.Println("二维切片b的排序结果: ")
for i := 0; i < len(b); i++ {
for j := 0; j < len(b[0]); j++ {
fmt.Print(b[i][j], " ")
}
fmt.Println()
}
}