sort
sort包提供了排序切片和用户自定义数据集的函数。
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
people := []Person{
{"Bob", 31},
{"John", 42},
{"Michael", 17},
{"Jenny", 26},
}
fmt.Println(people)
sort.Sort(ByAge(people))
fmt.Println(people)
}
type earthMass float64
type au float64
type Planet struct {
name string
mass earthMass
distance au
}
type By func(p1, p2 *Planet) bool
func (by By) Sort(planets []Planet) {
ps := &planetSorter{
planets: planets,
by: by,
}
sort.Sort(ps)
}
type planetSorter struct {
planets []Planet
by func(p1, p2 *Planet) bool // Closure used in the Less method.
}
func (s *planetSorter) Len() int {
return len(s.planets)
}
func (s *planetSorter) Swap(i, j int) {
s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}
func (s *planetSorter) Less(i, j int) bool {
return s.by(&s.planets[i], &s.planets[j])
}
var planets = []Planet{
{"Mercury", 0.055, 0.4},
{"Venus", 0.815, 0.7},
{"Earth", 1.0, 1.0},
{"Mars", 0.107, 1.5},
}
func main() {
name := func(p1, p2 *Planet) bool {
return p1.name < p2.name
}
mass := func(p1, p2 *Planet) bool {
return p1.mass < p2.mass
}
distance := func(p1, p2 *Planet) bool {
return p1.distance < p2.distance
}
decreasingDistance := func(p1, p2 *Planet) bool {
return !distance(p1, p2)
}
By(name).Sort(planets)
fmt.Println("By name:", planets)
By(mass).Sort(planets)
fmt.Println("By mass:", planets)
By(distance).Sort(planets)
fmt.Println("By distance:", planets)
By(decreasingDistance).Sort(planets)
fmt.Println("By decreasing distance:", planets)
}
type Change struct {
user string
language string
lines int
}
type lessFunc func(p1, p2 *Change) bool
type multiSorter struct {
changes []Change
less []lessFunc
}
func (ms *multiSorter) Sort(changes []Change) {
ms.changes = changes
sort.Sort(ms)
}
func OrderedBy(less ...lessFunc) *multiSorter {
return &multiSorter{
less: less,
}
}
func (ms *multiSorter) Len() int {
return len(ms.changes)
}
func (ms *multiSorter) Swap(i, j int) {
ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}
func (ms *multiSorter) Less(i, j int) bool {
p, q := &ms.changes[i], &ms.changes[j]
// Try all but the last comparison.
var k int
for k = 0; k < len(ms.less)-1; k++ {
less := ms.less[k]
switch {
case less(p, q):
return true
case less(q, p):
return false
}
}
return ms.less[k](p, q)
}
var changes = []Change{
{"gri", "Go", 100},
{"ken", "C", 150},
{"glenda", "Go", 200},
{"rsc", "Go", 200},
{"r", "Go", 100},
{"ken", "Go", 200},
{"dmr", "C", 100},
{"r", "C", 150},
{"gri", "Smalltalk", 80},
}
func main() {
user := func(c1, c2 *Change) bool {
return c1.user < c2.user
}
language := func(c1, c2 *Change) bool {
return c1.language < c2.language
}
increasingLines := func(c1, c2 *Change) bool {
return c1.lines < c2.lines
}
decreasingLines := func(c1, c2 *Change) bool {
return c1.lines > c2.lines // Note: > orders downwards.
}
OrderedBy(user).Sort(changes)
fmt.Println("By user:", changes)
OrderedBy(user, increasingLines).Sort(changes)
fmt.Println("By user,<lines:", changes)
OrderedBy(user, decreasingLines).Sort(changes)
fmt.Println("By user,>lines:", changes)
OrderedBy(language, increasingLines).Sort(changes)
fmt.Println("By language,<lines:", changes)
OrderedBy(language, increasingLines, user).Sort(changes)
fmt.Println("By language,<lines,user:", changes)
}
type Grams int
func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }
type Organ struct {
Name string
Weight Grams
}
type Organs []*Organ
func (s Organs) Len() int { return len(s) }
func (s Organs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
type ByName struct{ Organs }
func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name }
type ByWeight struct{ Organs }
func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }
func main() {
s := []*Organ{
{"brain", 1340},
{"heart", 290},
{"liver", 1494},
{"pancreas", 131},
{"prostate", 62},
{"spleen", 162},
}
sort.Sort(ByWeight{s})
fmt.Println("Organs by weight:")
printOrgans(s)
sort.Sort(ByName{s})
fmt.Println("Organs by name:")
printOrgans(s)
}
func printOrgans(s []*Organ) {
for _, o := range s {
fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
}
}
type Interface
type Interface interface {
// Len方法返回集合中的元素个数
Len() int
// Less方法报告索引i的元素是否比索引j的元素小
Less(i, j int) bool
// Swap方法交换索引i和j的两个元素
Swap(i, j int)
}
一个满足sort.Interface接口的(集合)类型可以被本包的函数进行排序。方法要求集合中的元素可以被整数索引。
type IntSlice
type IntSlice []int
IntSlice给[]int添加方法以满足Interface接口,以便排序为递增序列。
func (IntSlice) Len
func (p IntSlice) Len() int
func (IntSlice) Less
func (p IntSlice) Less(i, j int) bool
func (IntSlice) Swap
func (p IntSlice) Swap(i, j int)
func (IntSlice) Sort
func (p IntSlice) Sort()
Sort等价于调用Sort(p)
func (IntSlice) Search
func (p IntSlice) Search(x int) int
Search等价于调用SearchInts(p, x)
type Float64Slice
type Float64Slice []float64
Float64Slice给[]float64添加方法以满足Interface接口,以便排序为递增序列。
func (Float64Slice) Len
func (p Float64Slice) Len() int
func (Float64Slice) Less
func (p Float64Slice) Less(i, j int) bool
func (Float64Slice) Swap
func (p Float64Slice) Swap(i, j int)
func (Float64Slice) Sort
func (p Float64Slice) Sort()
Sort等价于调用Sort(p)
func (Float64Slice) Search
func (p Float64Slice) Search(x float64) int
Search等价于调用SearchFloat64s(p, x)
type StringSlice
type StringSlice []string
StringSlice给[]string添加方法以满足Interface接口,以便排序为递增序列。
func (StringSlice) Len
func (p StringSlice) Len() int
func (StringSlice) Less
func (p StringSlice) Less(i, j int) bool
func (StringSlice) Swap
func (p StringSlice) Swap(i, j int)
func (StringSlice) Sort
func (p StringSlice) Sort()
Sort等价于调用Sort(p)
func (StringSlice) Search
func (p StringSlice) Search(x string) int
Search等价于调用SearchStrings(p, x)
func Sort
func Sort(data Interface)
Sort排序data。它调用1次data.Len确定长度,调用O(n*log(n))次data.Less和data.Swap。本函数不能保证排序的稳定性(即不保证相等元素的相对次序不变)。
func Stable
func Stable(data Interface)
Stable排序data,并保证排序的稳定性,相等元素的相对次序不变。
它调用1次data.Len,O(nlog(n))次data.Less和O(nlog(n)*log(n))次data.Swap。
func IsSorted
func IsSorted(data Interface) bool
IsSorted报告data是否已经被排序。
func Reverse
func Reverse(data Interface) Interface
Reverse包装一个Interface接口并返回一个新的Interface接口,对该接口排序可生成递减序列。
func main() {
s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Sort(sort.Reverse(sort.IntSlice(s)))
fmt.Println(s)
// [6 5 4 3 2 1]
}
func Search
func Search(n int, f func(int) bool) int
Search函数采用二分法搜索找到[0, n)区间内最小的满足f(i)==true的值i。也就是说,Search函数希望f在输入位于区间[0, n)的前面某部分(可以为空)时返回假,而在输入位于剩余至结尾的部分(可以为空)时返回真;Search函数会返回满足f(i)==true的最小值i。如果没有该值,函数会返回n。注意,未找到时的返回值不是-1,这一点和strings.Index等函数不同。Search函数只会用区间[0, n)内的值调用f。
一般使用Search找到值x在插入一个有序的、可索引的数据结构时,应插入的位置。这种情况下,参数f(通常是闭包)会捕捉应搜索的值和被查询的数据集。
例如,给定一个递增顺序的切片,调用Search(len(data), func(i int) bool { return data[i] >= 23 })会返回data中最小的索引i满足data[i] >= 23。如果调用者想要知道23是否在切片里,它必须另外检查data[i] == 23。
搜索递减顺序的数据时,应使用<=运算符代替>=运算符。
下列代码尝试在一个递增顺序的整数切片中找到值x:
x := 23
i := sort.Search(len(data), func(i int) bool { return data[i] >= x })
if i < len(data) && data[i] == x {
// x is present at data[i]
} else {
// x is not present in data,
// but i is the index where it would be inserted.
}
一个更古怪的例子,下面的程序会猜测你持有的数字:
func GuessingGame() {
var s string
fmt.Printf("Pick an integer from 0 to 100.\n")
answer := sort.Search(100, func(i int) bool {
fmt.Printf("Is your number <= %d? ", i)
fmt.Scanf("%s", &s)
return s != "" && s[0] == 'y'
})
fmt.Printf("Your number is %d.\n", answer)
}
func Ints
func Ints(a []int)
Ints函数将a排序为递增顺序。
func main() {
s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Ints(s)
fmt.Println(s)
// [1 2 3 4 5 6]
}
func IntsAreSorted
func IntsAreSorted(a []int) bool
IntsAreSorted检查a是否已排序为递增顺序。
func SearchInts
func SearchInts(a []int, x int) int
SearchInts在递增顺序的a中搜索x,返回x的索引。如果查找不到,返回值是x应该插入a的位置(以保证a的递增顺序),返回值可以是len(a)。
func Float64s
func Float64s(a []float64)
Float64s函数将a排序为递增顺序。
func Float64sAreSorted
func Float64sAreSorted(a []float64) bool
Float64sAreSorted检查a是否已排序为递增顺序。
func SearchFloat64s
func SearchFloat64s(a []float64, x float64) int
SearchFloat64s在递增顺序的a中搜索x,返回x的索引。如果查找不到,返回值是x应该插入a的位置(以保证a的递增顺序),返回值可以是len(a)。
func Strings
func Strings(a []string)
Strings函数将a排序为递增顺序。
func StringsAreSorted
func StringsAreSorted(a []string) bool
StringsAreSorted检查a是否已排序为递增顺序。
func SearchStrings
func SearchStrings(a []string, x string) int
SearchStrings在递增顺序的a中搜索x,返回x的索引。如果查找不到,返回值是x应该插入a的位置(以保证a的递增顺序),返回值可以是len(a)。
有疑问加站长微信联系(非本文作者)