Overview

包sort提供排序切片和用户自定义集合的原语

函数(Functions)

func Float64s(a []float64)

Float64s以升序排序切片,NaN(not a number)被视为小于其它值

func Float64sAreSorted(a []float64) bool

检查float64s的切片是否已升序排序,NaN(not a number)被视为小于其它值

func Ints(a []int)

以升序排序整型切片

func IntsAreSorted(a []int) bool

检查整型切片是否是由升序排序

func IsSorted(data Interface) bool

IsSorted检查data是否已排序

func Search(n int, f func(int) bool) int

Search使用二分查找并返回最小的索引[0, n)符合f(i)是true,确保f(i) == true暗示着f(i + 1) == true,就是说,Search要求返回false对于一些输入[0,n)前缀(可能是空),剩下的为true,可能为空,Search返回第一个满足f(i) == true的索引,如果没有这样的索引,返回n.一个共同的使用Search是在已排序的集合,可索引的数据结构切片或数组

func SearchFloat64s(a []float64, x float64) int

SearchFloat64s在已升序排序的切片a中搜索符合插入x的位置 (可能为len(a)),该切片必须以升序排序.

func SearchInts(a []int, x int) int

SearchInts在已升序排序的切片a中搜索符合插入x的位置 (可能为len(a)),该切片必须以升序排序.

func SerachStrings(a []string, x string) int

SearchStrings在已升序排序的切片a中搜索符合插入x的位置 (可能为len(a)),该切片必须以升序排序.

func Slice(slice interface{}, less func(i, j int) bool)

Slice提供了给slice排序按指定的less function. 该函数不保证排序是稳定的,对于需要排序稳定的,使用SliceStable. 该函数panic,如果提供的slice不是切片

func SliceSorted(slice interface{}, less func(i, j int) bool) bool

SliceSorted检查slice是否已排序 如果slice不是切片,将会导致panic.

func SliceStable(slice interface{}, less func(i, j int) bool)

SliceStable以稳定排序算法排序slice 如果slice不是切片,将会导致panic

func Sort(data Interface)

Sort根据data实现的sort.Interface提供的接口方法进行排序,由data.Len提供终止的n,data.Less实现O(n*logn)复杂度的排序,data.Swap进行交换

func Stable(data Interface)

Stable提供了Sort的稳定排序形式

func Strings(a []string)

Strings以升序排序字符串切片.

func StringsAreSorted(a []string) bool

StringsAreSorted检查字符串切片是否以升序排序.

type Float64Slice


type Float64Slice []float64
Float64Slice实现了sort.Interface,以升序的排序切片,NaN(not a number)被视为小于其他值

func (p Float64Slice) Len() int

func (p Float64Slice) Less(i, j int) bool

func (p Float64Slice) Swap(i, j int) bool

func (p Float64Slice) Search(x float64)

返回接收者为p的SerachFloat64s的结果

func (p Float64Slice) Sort()

type IntSlice


type IntSlice []int
IntSlice实现了sort.Interface接口,以升序排序整型切片

func (p IntSlice) Len() int

func (p IntSlice) Less(i, j int) bool

func (p IntSlice) Swap(i, j int)

func (p IntSlice) Search(x int) int

Search返回应用SearchInts到接收者p和x

func (p IntSlice) Sort()

Sort是sort.Sort(p)的简单表示

type Interface


type Interface interface {
    Less(i, j int) bool
    Len() int
    Swap(i, j int)
}
为了排序定义的接口,通常集合会实现它,这些方法要求集合能够被整数索引

func Reverse(data Interface) Interface

Reverse返回data的逆序

type StringSlice


type StringSlice []string

func (p StringSlice) Len() int

func (p StringSlice) Less(i, j int) bool

func (p StringSlice) Swap(i, j int) bool

func (p StringSlice) Search(x string) int

func (p StringSlice) Sort()

Examples


两种方法排序

package sort_test

import (
	"sort"
	"fmt"
)

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 (ba ByAge) Len() int {
	return len(ba)
}

func (ba ByAge) Less(i, j int) bool {
	return ba[i].Age < ba[j].Age
}

func (ba ByAge) Swap(i, j int) {
	ba[i], ba[j] = ba[j], ba[i]
}

func Example() {
	people := []Person {
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}
	fmt.Println(people)
	// 第一种方法: 通过实现sort.Interface接口进行排序
	sort.Sort(ByAge(people))
	fmt.Println(people)
	// 第二种方法: 如果原生类型是切片,可以直接提供Less函数排序
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age > people[j].Age
	})
	fmt.Println(people)
	// Output:
	// [Bob: 31 John: 42 Michael: 17 Jenny: 26]
	// [Michael: 17 Jenny: 26 Bob: 31 John: 42]
	// [John: 42 Bob: 31 Jenny: 26 Michael: 17]
}

按照指定key排序

package sort_test

import (
	"sort"
	"fmt"
)

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
}

func (ps *PlanetSorter) Len() int {
	return len(ps.planets)
}
func (ps *PlanetSorter) Less(i, j int) bool {
	return ps.by(&ps.planets[i], &ps.planets[j])
}
func (ps *PlanetSorter) Swap(i, j int) {
	ps.planets[i], ps.planets[j] = ps.planets[j], ps.planets[i]
}

var planets = []Planet {
	{"Mercury", 0.055, 0.4},
	{"Venus", 0.815, 0.7},
	{"Earth", 1.0, 1.0},
	{"Mars", 0.107, 1.5},
}

func Example_sortkeys() {
	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(p2, p1)
	}
	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)
	// Output: By name: [{Earth 1 1} {Mars 0.107 1.5} {Mercury 0.055 0.4} {Venus 0.815 0.7}]
	// By mass: [{Mercury 0.055 0.4} {Mars 0.107 1.5} {Venus 0.815 0.7} {Earth 1 1}]
    // By distance: [{Mercury 0.055 0.4} {Venus 0.815 0.7} {Earth 1 1} {Mars 0.107 1.5}]
    // By decreasing distance: [{Mars 0.107 1.5} {Earth 1 1} {Venus 0.815 0.7} {Mercury 0.055 0.4}]
}

组合多个key进行排序

package sort_test


import (
	"sort"
	"fmt"
)

type Change struct {
	user string
	language string
	line int
}
type lessFunc func(p1, p2 *Change) bool
type MultiSorter struct {
	changes []Change
	less []lessFunc
}

func OrderBy(less ...lessFunc) *MultiSorter {
	return &MultiSorter {
		less: less,
	}
}

func (ms *MultiSorter) Sort(changes []Change) {
	ms.changes = changes
	sort.Sort(ms)
}
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 {
	for _, less := range ms.less {
		switch {
		case less(&ms.changes[i], &ms.changes[j]) :
			return true
		case less(&ms.changes[j], &ms.changes[i]):
			return false
		}
	}
	return ms.less[len(ms.less) - 1](&ms.changes[i], &ms.changes[j])
}
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 Example_sortMultiKeys() {
	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.line < c2.line
	}
	decreasingLines := func(c1, c2 *Change) bool {
		return increasingLines(c2, c1)
	}
	OrderBy(user).Sort(changes)
	fmt.Println("By user:", changes)
	OrderBy(user, increasingLines).Sort(changes)
	fmt.Println("By user,<lines:", changes)
	OrderBy(user, decreasingLines).Sort(changes)
	fmt.Println("By user,>lines:", changes)
	OrderBy(language, increasingLines).Sort(changes)
	fmt.Println("By language,<lines:", changes)
	OrderBy(language, increasingLines, user).Sort(changes)
	fmt.Println("By language,<lines,user:", changes)
	// Output:
    // By user: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
    // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {r Go 100} {gri Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
    // By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
}

组合封装成sort.Interface接口

package sort_test


import (
	"sort"
	"fmt"
)
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 printOrgans(s []*Organ) {
	for _, v := range s {
		fmt.Printf("%-8s (%v)\n", v.Name, v.Weight)
	}
}
func Example_sortWrapper() {
	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)
	// Output:
    // Organs by weight:
    // prostate (62g)
    // pancreas (131g)
    // spleen   (162g)
    // heart    (290g)
    // brain    (1340g)
    // liver    (1494g)
    // Organs by name:
    // brain    (1340g)
    // heart    (290g)
    // liver    (1494g)
    // pancreas (131g)
    // prostate (62g)
    // spleen   (162g)
}