排序整数、浮点数和字符串切片
sort:排序,提供了对切片和用户定义的集合进行排序
对于[]int ,[]float.[]string这种元素类型时基础类型的切片使用sort包提供了下面几个函数进行排序:
- sort.Ints
- sort.Floats
- sort.Strings
package main
import (
"fmt"
"sort"
)
func main() {
intList := [] int {2, 4, 3, 5, 7}
float8List := [] float64 {4.2, 5.9, 12.3, 10.0}
stringList := [] string {"a", "c", "b", "w", "y"}
sort.Ints(intList)
sort.Float64s(float8List)
sort.Strings(stringList)
fmt.Printf("%v\n%v\n%v\n", intList, float8List, stringList)
intListt := [] int {2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
float8Listt := [] float64 {4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
stringListt := [] string {"a", "c", "b", "d", "f", "i", "z", "x", "w", "y"}
//IntSlice将interface的方法附加到[]int上并按递增顺序排序
s :=sort.IntSlice(intListt)
sort.Sort(s)//递增
fmt.Println("s",s)
//Reverse:返回数据的反响顺序
sort.Sort(sort.Reverse(sort.Float64Slice(float8Listt)))//递减
sort.Sort(sort.Reverse(sort.StringSlice(stringListt)))
fmt.Printf("%v\n%v\n%v\n", intListt, float8Listt, stringListt)
}
输出
[2 3 4 5 7]
[4.2 5.9 10 12.3]
[a b c w y]
s [0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[99.9 50.4 31.4 27.81828 12.3 10 5.9 4.2 3.14]
[z y x w i f d c b a]
使用自定义比较器排序
- 使用sort.Slice函数排序,它使用一个用户提供的函数来对序列进行排序,函数类型为func(i, j int) bool,其中参数i, j是序列中的索引。
- sort.SliceStable在排序切片时会保留相等元素的原始顺序。
- 上面两个函数让我们可以排序结构体切片(order by struct field value)。
family := []struct {
Name string
Age int
}{
{"Alice", 23},
{"David", 2},
{"Eve", 2},
{"Bob", 25},
}
// 用 age 排序,年龄相等的元素保持原始顺序
sort.SliceStable(family, func(i, j int) bool {
return family[i].Age < family[j].Age
})
fmt.Println(family) // [{David 2} {Eve 2} {Alice 23} {Bob 25}]
排序任意数据结构
- 使用sort.Sort或者sort.Stable函数。
- 他们可以排序实现了sort.Interface接口的任意类型
一个内置的排序算法需要知道三个东西:序列的长度,表示两个元素比较的结果,一种交换两个元素的方式;这就是sort.Interface的三个方法:
type Interface interface {
Len() int
Less(i, j int) bool // i, j 是元素的索引
Swap(i, j int)
}
还是以上面结构体切片为例子,我们为切片类型自定义一个类型名,然后在自定义的类型上实现srot.Interfce
接口
type Person struct {
Name string
Age int
}
// ByAge 通过对age排序实现了sort.Interface接口
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
family := []Person{
{"David", 2},
{"Alice", 23},
{"Eve", 2},
{"Bob", 25},
}
sort.Sort(ByAge(family))
fmt.Println(family) // [{David, 2} {Eve 2} {Alice 23} {Bob 25}]
}
实现了sort.Interface的具体类型不一定是切片类型;下面的customSort是一个结构体类型。
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
//实现sort.Interface的具体类型不一定是切片类型;下面的customSort是一个结构体类型
type customSort struct {
p []Person
less func(x, y Person) bool
}
func (x customSort) Len() int {return len(x.p)}
func (x customSort) Less(i, j int) bool { return x.less(x.p[i], x.p[j]) }
func (x customSort) Swap(i, j int) { x.p[i], x.p[j] = x.p[j], x.p[i] }
func main() {
family := []Person{
{"David", 2},
{"Alice", 23},
{"Eve", 2},
{"Bob", 25},
}
//func Sort(data Interface):对data进行排序。他调用一次data.Len来决定排序的长度 n。
//调用data.Less和data.Swap的开销为O(n*log(n)), 此排序为不稳定排序。他根据不同形式决定使用不用的排序方式(插入排序,堆排序,快排)
//定义一个根据多字段排序的函数,它主要的排序键是Age,Age 相同了再按 Name 进行倒序排序。
//下面是该排序的调用,其中这个排序使用了匿名排序函数:
sort.Sort(customSort{family, func(x, y Person) bool {
if x.Age !=y.Age {
return x.Age<y.Age
}
if x.Name !=x.Name {
return x.Name>y.Name
}
return false
}})
fmt.Println(family)
}