老男孩教育专注IT教育10余年,只培养IT技术精英

全国免费咨询电话(渠道合作):400-609-2893

Go语言sort包排序!老男孩IT教育

老男孩IT教育

技术博客

2021年2月21日 14:59

Go语言 sort包提供了排序切片和用户自定义数据集的函数。

  Go语言 sort包提供了排序切片和用户自定义数据集的函数。

  基本类型排序

  1、升序排序

  对于 int 、 float64 和 string 数组或是分片的排序, go 分别提供了 sort.Ints() 、 sort.Float64s() 和 sort.Strings() 函数, 默认都是从小到大排序。

package main

import (
    "fmt"
    "sort"
)

func main() {
    intList1 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
    floatList1 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
    stringList1 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}

    // 方法一
    sort.Ints(intList1)
    sort.Float64s(floatList1)
    sort.Strings(stringList1)
    fmt.Printf("方法一:\n%v\n%v\n%v\n", intList1, floatList1, stringList1)

    // 方法二
    intList2 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
    floatList2 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
    stringList2 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
    sort.Sort(sort.IntSlice(intList2))
    sort.Sort(sort.Float64Slice(floatList2))
    sort.Sort(sort.StringSlice(stringList2))
    fmt.Printf("方法二:\n%v\n%v\n%v\n", intList2, floatList2, stringList2)

    // 方法三
    intList3 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
    floatList3 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
    stringList3 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
    (sort.IntSlice(intList3)).Sort()
    (sort.Float64Slice(floatList3)).Sort()
    (sort.StringSlice(stringList3)).Sort()
    fmt.Printf("方法二:\n%v\n%v\n%v\n", intList3, floatList3, stringList3)
}

  2、降序排序

  sort 包下的三个类型 IntSlice 、 Float64Slice 、 StringSlice 分别实现了这三个方法, 对应排序的是 [] int 、 [] float64 和 [] string 。如果期望逆序排序, 只需要将对应的 Less 函数简单修改一下即可。

  go 的 sort 包可以使用 sort.Reverse(slice) 来调换 slice.Interface.Less ,也就是比较函数,所以, int 、 float64 和 string 的逆序排序函数可以这么写:

package main

import (
    "fmt"
    "sort"
)

func main() {
    intList := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
    floatList := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
    stringList := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}

    sort.Sort(sort.Reverse(sort.IntSlice(intList)))
    sort.Sort(sort.Reverse(sort.Float64Slice(floatList)))
    sort.Sort(sort.Reverse(sort.StringSlice(stringList)))

    fmt.Printf("%v\n%v\n%v\n", intList, floatList, stringList)
}

  结构体类型的排序

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

  1、模拟 IntSlice 排序

package main

import (
    "fmt"
    "sort"
)

type Student struct {
    Name string
    Age  int
}

// 按照 Student.Age 从大到小排序
type StudentSlice []Student

// 重写 Len() 方法
func (a StudentSlice) Len() int {
    return len(a)
}

// 重写 Swap() 方法
func (a StudentSlice) Swap(i, j int) {
    a[i], a[j] = a[j], a[i]
}

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

func main() {
    stu := []Student{
        {"zhang san", 18},
        {"li si", 28},
        {"wang wu", 25},
        {"zhao liu", 16},
        {"oldboy", 20},
    }

    fmt.Println(stu)
    // 按照 Age 的降序排序
    sort.Sort(StudentSlice(stu))
    fmt.Println(stu)
    // 按照 Age 的升序排序
    sort.Sort(sort.Reverse(StudentSlice(stu)))
    fmt.Println(stu)

}

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

  2、进一步封装,封装成 SortStudent 方法:

package main

import (
    "fmt"
    "sort"
)

type Student struct {
    Name string
    Age  int
}

type StudentWrapper struct {
    stu []Student
    by  func(p, q *Student) bool
}

type SortBy func(p, q *Student) bool

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

// 封装成 SortStudent 方法
func SortStudent(stu []Student, by SortBy) {
    sort.Sort(StudentWrapper{stu, by})
}

func main() {
    stu := []Student{
        {"zhang san", 18},
        {"li si", 28},
        {"wang wu", 25},
        {"zhao liu", 16},
        {"oldboy", 20},
    }

    fmt.Println(stu)

    sort.Sort(StudentWrapper{stu, func(p, q *Student) bool {
        return q.Age < p.Age // Age 递减排序
    }})

    fmt.Println(stu)

    SortStudent(stu, func(p, q *Student) bool {
        return p.Name < q.Name // Name 递增排序
    })
    fmt.Println(stu)
}

  推荐阅读:

  GO语言入门学习之Channel管道

  GO语言培训之什么是互斥锁?

  Go语言模板渲染!老男孩教育

本文经授权发布,不代表老男孩教育立场。如若转载请联系原作者。