要点
Go的Sort是对一个数据数列进行排序,但不保证stable。——关于stable,请参考数据结构或算法相关介绍。
Interface接口
要使用Sort功能,需要这个数据对象实现sort package中的接口(3个方法):
// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
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)
}
这里其实隐含要求这个容器或数据集合是slice类型或Array类型。否则,没法按照索引号取值。
另外,Go的sort要实现的这个接口类似于Java的Comparable接口。C++ STL的sort则要提供一个operator<的binary function。基本思想基本是一致的,只是Go的要求更为严格。
XXXSlice & XXXs
Go的sort包已经为基本数据类型都实现了sort功能,其函数名的最后一个字母是s,表示sort之意。比如:Ints, Float64s, Strings,等等。
对应的,int、float64、string等这些基本数据类型对应的集合类似,则被命名为IntSlice、Float64Slice、StringSlice等。
只需要看源码即可了解前述内容,拷贝如下:
// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
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] }
// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }
注意这里的Ints(), Sort(), IntSlice()几个函数之间的关系,并对比下面示例中的两种排序步骤。
示例
这里直接取sort_test.go中的部分代码,文件名也要符合test的命名规范,参考Go-Tesing:
package main
import (
//"fmt"
"sort"
"math"
"testing"
)
var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
var float64s = [...]float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8}
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
func TestSortIntSlice(t *testing.T) {
data := ints
a := sort.IntSlice(data[0:])
sort.Sort(a)
if !sort.IsSorted(a) {
t.Errorf("sorted %v", ints)
t.Errorf(" got %v", data)
}
}
func TestSortFloat64Slice(t *testing.T) {
data := float64s
a := sort.Float64Slice(data[0:])
sort.Sort(a)
if !sort.IsSorted(a) {
t.Errorf("sorted %v", float64s)
t.Errorf(" got %v", data)
}
}
func TestSortStringSlice(t *testing.T) {
data := strings
a := sort.StringSlice(data[0:])
sort.Sort(a)
if !sort.IsSorted(a) {
t.Errorf("sorted %v", strings)
t.Errorf(" got %v", data)
}
}
func TestInts(t *testing.T) {
data := ints
sort.Ints(data[0:])
if !sort.IntsAreSorted(data[0:]) {
t.Errorf("sorted %v", ints)
t.Errorf(" got %v", data)
}
}
func TestFloat64s(t *testing.T) {
data := float64s
sort.Float64s(data[0:])
if !sort.Float64sAreSorted(data[0:]) {
t.Errorf("sorted %v", float64s)
t.Errorf(" got %v", data)
}
}
func TestStrings(t *testing.T) {
data := strings
sort.Strings(data[0:])
if !sort.StringsAreSorted(data[0:]) {
t.Errorf("sorted %v", strings)
t.Errorf(" got %v", data)
}
}
自定义数据类型
package main
import (
"fmt"
"sort"
)
type Person struct {
name string
age int
}
type Persons []Person
func (ps Persons) Len() int {
return len(ps)
}
func (ps Persons) Less(i, j int) bool {
return ps[i].name < ps[j].name
}
func (ps Persons) Swap(i, j int) {
temp := ps[i]
ps[i] = ps[j]
ps[j] = temp
}
func main() {
// first style
persons := []Person{
{"Tom", 5},
{"Jerry", 6},
}
sort.Sort(Persons(persons))
fmt.Println(persons)
// second style
persons2 := Persons{
{"_Tom", 5},
{"_Jerry", 6},
}
sort.Sort(persons2)
fmt.Println(persons2)
}
有疑问加站长微信联系(非本文作者)