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

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

Less() 函数即可。

上面的 Reverse 是个通用的结构体。

上面说了那么多, 只是对基本类型进行排序, 该到说说 struct 结构体类型的排序的时候了, 实际中这个用得到的会更多。

结构体类型的排序

结构体类型的排序是通过使用 sort.Sort(slice) 实现的, 只要 slice 实现了 sort.Interface 的三个方法就可以。 虽然这么说,但是排序的方法却有那么好几种。首先一种就是模拟排序 [] int 构造对应的 IntSlice 类型,然后对 IntSlice 类型实现 Interface 的三个方法。

1、模拟 IntSlice 排序

package main

import (
 "fmt"
 "sort"
)

type Person struct {
 Name string
 Age int
}

// 按照 Person.Age 从大到小排序
type PersonSlice [] Person

func (a PersonSlice) Len() int {   // 重写 Len() 方法
 return len(a)
}
func (a PersonSlice) Swap(i, j int){  // 重写 Swap() 方法
 a[i], a[j] = a[j], a[i]
}
func (a PersonSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序
 return a[j].Age < a[i].Age
}

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

 fmt.Println(people)

 sort.Sort(PersonSlice(people)) // 按照 Age 的逆序排序
 fmt.Println(people)

 sort.Sort(sort.Reverse(PersonSlice(people))) // 按照 Age 的升序排序
 fmt.Println(people)

}

这完全是一种模拟的方式,所以如果懂了 IntSlice 自然就理解这里了,反过来,理解了这里那么 IntSlice 那里也就懂了。

这种方法的缺点是:根据 Age 排序需要重新定义 PersonSlice 方法,绑定 Len 、 Less 和 Swap 方法, 如果需要根据 Name 排序, 又需要重新写三个函数; 如果结构体有 4 个字段,有四种类型的排序,那么就要写 3 × 4 = 12 个方法, 即使有一些完全是多余的, O__O”… 仔细思量一下,根据不同的标准 Age 或是 Name, 真正不同的体现在 Less 方法上,所以可以将 Less 抽象出来, 每种排序的 Less 让其变成动态的,比如下面一种方法。

2、封装成 Wrapper

package main

import (
 "fmt"
 "sort"
)

type Person struct {
 Name string
 Age int
}

type PersonWrapper struct {     //注意此处
 people [] Person
 by 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])
}

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)
 sort.Sort(PersonWrapper{people, func (p, q *Person) bool {
  return p.Name < q.Name // Name 递增排序
 }})

 fmt.Println(people)

}
            




              

微信扫一扫

易采站长站微信账号