惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Latest
Security Latest
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
N
Netflix TechBlog - Medium
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
C
Cyber Attacks, Cyber Crime and Cyber Security
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MyScale Blog
MyScale Blog
T
Tor Project blog
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
P
Privacy & Cybersecurity Law Blog
MongoDB | Blog
MongoDB | Blog
Simon Willison's Weblog
Simon Willison's Weblog
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
小众软件
小众软件
G
GRAHAM CLULEY
P
Privacy International News Feed
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
人人都是产品经理
人人都是产品经理
S
Schneier on Security
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
T
The Exploit Database - CXSecurity.com
Recent Announcements
Recent Announcements
E
Exploit-DB.com RSS Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
U
Unit 42
The Register - Security
The Register - Security
S
Securelist
Martin Fowler
Martin Fowler
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
Cisco Talos Blog
Cisco Talos Blog

博客园 - 自然洒脱

MiniMax 权益码 Token Plan 套餐 9 折优惠 go语言context包 go语言通道 go语言GMP模型 go语言mongodb操作 go语言gorm的CRUD go语言gorm go语言mysql驱动 go语言log相关 go语言包管理 go语言时间相关 go语言序列化和反序列化 go语言的"面向对象" go语言异常处理 go语言接口 go语言结构体(二) go语言结构体(一) go语言递归函数及defer go语言函数作用域及匿名函数
go语言结构体排序
自然洒脱 · 2023-07-05 · via 博客园 - 自然洒脱

排序接口

从接口定义来看,要实现某类型的排序 要知道有多少个元素 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排序

下面为返回结果