深入理解golang的基本类型排序与slice排序

2019-11-10 10:44:22 来源:易采站长站 作者:丽君

这种方法将 [] Person 和比较的准则 cmp 封装在了一起,形成了 PersonWrapper 函数,然后在其上绑定 Len 、 Less 和 Swap 方法。 实际上 sort.Sort(pw) 排序的是 pw 中的 people, 这就是前面说的, go 的排序未必就是针对的一个数组或是 slice, 而可以是一个对象中的数组或是 slice 。

3、进一步封装

感觉方法 2 已经很不错了, 唯一一个缺点是,在 main 中使用的时候暴露了 sort.Sort 的使用,还有就是 PersonWrapper 的构造。 为了让 main 中使用起来更为方便, me 们可以再简单的封装一下, 构造一个 SortPerson 方法, 如下:

package main

import (
 "fmt"
 "sort"
)

type Person struct {
 Name string
 Age int
}

type PersonWrapper struct {
 people [] Person
 by func(p, q * Person) bool
}

type SortBy func(p, q *Person) bool

func (pw PersonWrapper) Len() int {   // 重写 Len() 方法
 return len(pw.people)
}
func (pw PersonWrapper) Swap(i, j int){  // 重写 Swap() 方法
 pw.people[i], pw.people[j] = pw.people[j], pw.people[i]
}
func (pw PersonWrapper) Less(i, j int) bool { // 重写 Less() 方法
 return pw.by(&pw.people[i], &pw.people[j])
}

// 封装成 SortPerson 方法
func SortPerson(people [] Person, by SortBy){
 sort.Sort(PersonWrapper{people, by})
}

func main() {
 people := [] Person{
  {"zhang san", 12},
  {"li si", 30},
  {"wang wu", 52},
  {"zhao liu", 26},
 }

 fmt.Println(people)

 sort.Sort(PersonWrapper{people, func (p, q *Person) bool {
  return q.Age < p.Age // Age 递减排序
 }})

 fmt.Println(people)

 SortPerson(people, func (p, q *Person) bool {
  return p.Name < q.Name // Name 递增排序
 })

 fmt.Println(people)

}

在方法 2 的基础上构造了 SortPerson 函数,使用的时候传过去一个 [] Person 和一个 cmp 函数。

4、另一种思路

package main

import (
 "fmt"
 "sort"
)

type Person struct {
 Name  string
 Weight  int
}

type PersonSlice []Person

func (s PersonSlice) Len() int { return len(s) }
func (s PersonSlice) Swap(i, j int)  { s[i], s[j] = s[j], s[i] }

type ByName struct{ PersonSlice } // 将 PersonSlice 包装起来到 ByName 中

func (s ByName) Less(i, j int) bool  { return s.PersonSlice[i].Name < s.PersonSlice[j].Name } // 将 Less 绑定到 ByName 上


type ByWeight struct{ PersonSlice } // 将 PersonSlice 包装起来到 ByWeight 中
func (s ByWeight) Less(i, j int) bool { return s.PersonSlice[i].Weight < s.PersonSlice[j].Weight } // 将 Less 绑定到 ByWeight 上

func main() {
 s := []Person{
  {"apple", 12},
  {"pear", 20},
  {"banana", 50},
  {"orange", 87},
  {"hello", 34},
  {"world", 43},
 }

 sort.Sort(ByWeight{s})
 fmt.Println("People by weight:")
 printPeople(s)

 sort.Sort(ByName{s})
 fmt.Println("nPeople by name:")
 printPeople(s)

}

func printPeople(s []Person) {
 for _, o := range s {
  fmt.Printf("%-8s (%v)n", o.Name, o.Weight)
 }
}

对结构体的排序, 暂时就到这里。 第一种排序对只根据一个字段的比较合适, 另外三个是针对可能根据多个字段排序的。方法 4 我认为每次都要多构造一个 ByXXX , 颇为不便, 这样多麻烦,不如方法 2 和方法 3 来的方便,直接传进去一个 cmp。 方法2、 3 没有太大的差别, 3 只是简单封装了一下而已, 对于使用者来说, 可能会更方便一些,而且也会更少的出错。

微信扫一扫

易采站长站微信账号