go标准库sort之基本使用
官方抽象出来的排序接口
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) }
提供了对int float string三种类型的排序
使用说明在example里面有详细写到
总结出来是四种常用的方式
1 简单的对类型的slice进行排序
2 使用比较的函数类型封装比较操作
3 支持多种比较函数
4 把需要比较的对象作为匿名对象迁移struct里面,通过struct方法进行比较
官方例子
1 使用slice进行简单排序
type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("%s: %d", p.Name, p.Age) } // ByAge implements sort.Interface for []Person based on // the Age field. 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) // Output: // [Bob: 31 John: 42 Michael: 17 Jenny: 26] // [Michael: 17 Jenny: 26 Bob: 31 John: 42] }
2 使用函数类型封装比较排序的函数
type Planet struct { name string mass earthMass distance au } // By is the type of a "less" function that defines the ordering of its Planet arguments. type By func(p1, p2 *Planet) bool // Sort is a method on the function type, By, that sorts the argument slice according to the function. func (by By) Sort(planets []Planet) { ps := &planetSorter{ planets: planets, by: by, // The Sort method's receiver is the function (closure) that defines the sort order. } sort.Sort(ps) } // planetSorter joins a By function and a slice of Planets to be sorted. type planetSorter struct { planets []Planet by func(p1, p2 *Planet) bool // Closure used in the Less method. } // Len is part of sort.Interface. func (s *planetSorter) Len() int { return len(s.planets) } // Swap is part of sort.Interface. func (s *planetSorter) Swap(i, j int) { s.planets[i], s.planets[j] = s.planets[j], s.planets[i] } // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter. func (s *planetSorter) Less(i, j int) bool { return s.by(&s.planets[i], &s.planets[j]) }
3 支持多个比较函数
// A Change is a record of source code changes, recording user, language, and delta size. type Change struct { user string language string lines int } type lessFunc func(p1, p2 *Change) bool // multiSorter implements the Sort interface, sorting the changes within. type multiSorter struct { changes []Change less []lessFunc } // Sort sorts the argument slice according to the less functions passed to OrderedBy. func (ms *multiSorter) Sort(changes []Change) { ms.changes = changes sort.Sort(ms) } // OrderedBy returns a Sorter that sorts using the less functions, in order. // Call its Sort method to sort the data. func OrderedBy(less ...lessFunc) *multiSorter { return &multiSorter{ less: less, } } // Len is part of sort.Interface. func (ms *multiSorter) Len() int { return len(ms.changes) } // Swap is part of sort.Interface. func (ms *multiSorter) Swap(i, j int) { ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i] } // Less is part of sort.Interface. It is implemented by looping along the // less functions until it finds a comparison that is either Less or // !Less. Note that it can call the less functions twice per call. We // could change the functions to return -1, 0, 1 and reduce the // number of calls for greater efficiency: an exercise for the reader. 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): // p < q, so we have a decision. return true case less(q, p): // p > q, so we have a decision. return false } // p == q; try the next comparison. } // All comparisons to here said "equal", so just return whatever // the final comparison reports. return ms.less[k](p, q) }
4 其实是第一种的变种
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] } // ByName implements sort.Interface by providing Less and using the Len and // Swap methods of the embedded Organs value. type ByName struct{ Organs } func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name } // ByWeight implements sort.Interface by providing Less and using the Len and // Swap methods of the embedded Organs value. type ByWeight struct{ Organs } func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }