排序接口

从接口定义来看,要实现某类型的排序 要知道有多少个元素 2个指定索引的元素怎么比较大小,索引i的元素小于索引j的值返回true,反之返回false 如何交换指定索引上的元素 那么自定义类型,要想排序,就要实现sort包中该接口。

结构体排序

 假设有N个学生,学生有姓名和年龄,按照年龄排序结构体实例。 学生使用结构体Student,多个学生就使用切片[ ]Student。 参照 sort.Ints() 的实现。

func Ints(x []int) { Sort(IntSlice(x)) } 观察这个方法,它依赖下面的定义
// IntSlice attaches the methods of Interface to []int, sorting in increasing 
order.
type IntSlice []int
func (x IntSlice) Len() int           { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x IntSlice) Swap(i, j int)     { x[i], x[j] = x[j], x[i] }

 就是要在[]Student上实现Interface接口的Len、Less、Swap方法。为了方便可以定义一个新类型,好实现方法。sort.Slice(待排序切片,less函数) 方法为简化版。

type Student struct {
    name string
    age  int
}

func main() {
    stu := make([]Student, 0, 10)
    for i := 0; i < 10; i++ {
        r := rand.Intn(128)
        stu = append(stu, Student{"Tom" + string(r), r})
    }
    fmt.Printf("%+v\n", stu)

    sort.Slice(stu, func(i, j int) bool {
        return stu[i].age < stu[j].age
    })
    fmt.Printf("%+v\n", stu)
}

下面是运行结果

 

map的排序

map是键值对的集合,是无序的hash表。但是排序输出是序列,也就是排序所需的键或值要存入序列 中,然后才能排序。

key排序

提取key为序列,排序后,用有序序列中的key映射value输出

package main
import (
    "fmt"
    "sort"
)
func main() {
    // To create a map as input
    m := make(map[int]string)
    m[1] = "a"
    m[2] = "c"
    m[0] = "b"
    // To store the keys in slice in sorted order
    var keys []int
    for k := range m {
        keys = append(keys, k)
   }
    sort.Ints(keys)
    // key排好序,就可以用key找到value了
    for _, k := range keys {
        fmt.Println("Key:", k, "Value:", m[k])
   }
}
示例

value排序

不能使用key排序思路,想象每一个键值对就是一个{key:xxx, value:yyy}的结构体实例,就转换成了结构体序列排序了。

package main
import (
 "fmt"
 "sort"
)
type Entry struct {
 Key   int
 Value string
}
func main() {
 m := make(map[int]string)
 m[1] = "a"
 m[2] = "c"
 m[0] = "b"
 entries := make([]Entry, len(m))
 i := 0 // 为什么用了i
 for k, v := range m {
 entries[i] = Entry{k, v}
 i++
 }
 fmt.Println(entries)
 sort.Slice(entries, func(i, j int) bool {
 return entries[i].Value < entries[j].Value
 }) // Value升序
 fmt.Println(entries)
}
示例

下面为一个题:

实现对圆形、三角形、长方形求面积,并图形按照面积降序排列

package main

import (
    "fmt"
    "math"
    "sort"
)

type Area interface {
    area() float32
}

type Graph struct {
    name string
}

// 三角形结构体
type Triangle struct {
    Graph
    lenth, high float32
}

// 圆形结构体
type Round struct {
    Graph
    rad float32
}

// 长方形结构体
type Rect struct {
    Graph
    lenth, wid float32
}

func (p *Triangle) area() float32 {
    area := p.lenth * p.high / 2
    return area
}

func (p *Round) area() float32 {
    area := float32(math.Pi * math.Pow(float64(p.rad), 2))
    return area
}

func (p *Rect) area() float32 {
    area := p.lenth * p.wid
    return area
}

// 多态实现
func area(a Area) float32 {
    return a.area()
}

// 用于map排序结构体
type gras struct {
    name Area
    area float32
}

func main() {
    // 三角形初始化实例并赋值
    t0 := &Triangle{lenth: 13, high: 16.9}
    // 圆形初始化实例并赋值
    ro0 := new(Round)
    ro0.rad = 23.5
    // 长方形初始化实例并赋值
    re0 := &Rect{lenth: 3.6, wid: 17}
    // 分别求各个图形的面积
    fmt.Printf("%v\n", area(t0))
    fmt.Printf("%v\n", area(ro0))
    fmt.Printf("%v\n", area(re0))

    // 对以上图形面积排序
    s0 := []gras{gras{t0, t0.area()}, gras{ro0, ro0.area()}, gras{re0, re0.area()}}
    fmt.Printf("排序前: %v\n", s0)
    sort.Slice(s0, func(i, j int) bool {
        return s0[i].area > s0[j].area
    })
    fmt.Printf("排序后: %v\n", s0)
}
对切片排序

下面为返回结果

 

package main

import (
    "fmt"
    "math"
    "sort"
)

type Area interface {
    area() float32
}

type Graph struct{}

// 三角形结构体
type Triangle struct {
    Graph
    lenth, high float32
}

// 圆形结构体
type Round struct {
    Graph
    rad float32
}

// 长方形结构体
type Rect struct {
    Graph
    lenth, wid float32
}

func (p *Triangle) area() float32 {
    area := p.lenth * p.high / 2
    return area
}

func (p *Round) area() float32 {
    area := float32(math.Pi * math.Pow(float64(p.rad), 2))
    return area
}

func (p *Rect) area() float32 {
    area := p.lenth * p.wid
    return area
}

// 多态实现
func area(a Area) float32 {
    return a.area()
}

// 用于map排序结构体
type gras struct {
    name Area
    area float32
}

func main() {
    // 三角形初始化实例并赋值
    t0 := new(Triangle)
    t0.lenth = 3
    t0.high = 6.9
    // 圆形初始化实例并赋值
    ro0 := new(Round)
    ro0.rad = 3.5
    // 长方形初始化实例并赋值
    re0 := new(Rect)
    re0.lenth = 13.6
    re0.wid = 17
    // 分别求各个图形的面积
    fmt.Printf("%v\n", area(t0))
    fmt.Printf("%v\n", area(ro0))
    fmt.Printf("%v\n", area(re0))

    // 对以上图形面积排序
    m0 := make(map[Area]float32, 100)
    m0[t0] = area(t0)
    m0[ro0] = area(ro0)
    m0[re0] = area(re0)
    slis := make([]gras, 3)
    i := 0
    for k, v := range m0 {
        slis[i] = gras{k, v}
        i++
    }
    fmt.Printf("排序前: %v\n", slis)
    sort.Slice(slis, func(i, j int) bool {
        return slis[i].area > slis[j].area
    })
    fmt.Printf("排序后: %v\n", slis)
}
对map排序

下面为返回结果

 

posted on 2023-07-05 19:54  自然洒脱  阅读(94)  评论(0编辑  收藏  举报