golang 使用sort.slice包实现对象list排序
作者:峰啊疯了 发布时间:2023-06-21 18:25:46
标签:golang,sort,slice,对象,list,排序
1.sort.Sort介绍
使用sort.Slice
进行排序,因为slice把struct抽象化了,且slice封装过了,简单的基础类型可以使用sort,使用sort排序需要重写三个interface,不想学习sort排序的可以直接看第三步
这里将对比sort跟slice两种排序的使用方式
1.1分析内置sort包
1.2分析sort.go
要想实现自定义对象的排序功能,需要重写这三个interface
外部调用sort
方法即可实现排序
func Sort(data Interface) {
n := data.Len()
quickSort(data, 0, n, maxDepth(n))
}
通过sort源码可以看到用的快速排序,不懂快排的可以自行重温快排算法,这里就不讲解快排原理了
2.使用方法
2.1基础类型排序
基础类型的排序直接在sort.go
去找就行了
package main
import (
"fmt"
"sort"
)
func main() {
intList := [] int {2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
float8List := [] float64 {4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
stringList := [] string {"a", "c", "b", "d", "f", "i", "z", "x", "w", "y"}
sort.Ints(intList)
sort.Float64s(float8List)
sort.Strings(stringList)
fmt.Printf("%v\n%v\n%v\n", intList, float8List, stringList)
}
2.2对象排序(单一字段)
如果对一个struct
对象的某一个字段进行排序就需要重写一组len,less,swap接口,如果有多组就需要重写多组接口。
下面直接看例子:
如果一个对象只有一个字段需要排序就用下面的例子比较简单
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)
}
2.3对象排序(多字段)
多个了SortBy
方法可以确定是升序还是降序,同时可以确定排序字段是哪个
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)
//推荐用封装的SortPerson方法
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)
}
如果不喜欢用sortby
方法,也可以重写多个less、len、swap方法,
下面的方法就调用起来比较简单,不用重写by跟sortby方法,但是上面的比较灵活(理解可能比下面的费劲)
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)
}
}
3.sort.Slice介绍
3.1使用方法
很明显将对象抽象成interface
,而上面对对象的排序,只能是person
这种特定对象
调用的时候有点类似java的重写compare
方法
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Weight int
}
func main() {
s := []Person{
{"apple", 12},
{"pear", 20},
{"banana", 50},
{"orange", 87},
{"hello", 34},
{"world", 43},
}
//可以向上面一样对排序字段封装,加一个sortby字段传递
sort.Slice(s,func(i,j int)bool{
return s[i].Weight < s[j].Weight
})
fmt.Println("People by weight:")
printPeople(s)
sort.Slice(s,func(i,j int)bool{
return s[i].Name < s[j].Name
})
fmt.Println("\nPeople by name:")
printPeople(s)
}
func printPeople(s []Person) {
for _, o := range s {
fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
}
}
3.2运行
来源:https://blog.51cto.com/u_12040959/5111341


猜你喜欢
- 前端版本更新检查,实现页面自动刷新使用vite对项目进行打包,对 js 和 css 文件使用了 chunkhash 进行了文件缓存控制,但是
- 一、块(Block)是PL/SQL的基本执行单元,由定义部分,执行部分(必须)和例外处理部分组成。Declare/*定义部分――定义常量、变
- 本文实例讲述了python实现从尾到头打印单链表操作。分享给大家供大家参考,具体如下:# coding=utf-8class SingleN
- 在写python程序时,对于可变对象和不可变对象这里理解不深,导致总会犯一些细节错误。以下面的程序举例:ab = {'a':
- 超文本传输协议http构成了万维网的基础,它利用URI(统一资源标识符)来识别Internet上的数据,而指定文档地址的URI被称为URL(
- 几个特殊的函数(待补充)python是支持多种范型的语言,可以进行所谓函数式编程,其突出体现在有这么几个函数: filter、map、red
- SQL Update常见写法Oralce和DB2都支持的语法:update test1?set (test1.name,test1.age)
- 一、算术运算符运算符+-*/%**(幂)求次方//(取整除,向下取整)如:9//2 =4二、比较运算符运算符==!=<>(不等于
- 一、概念官方描述:当打包构建应用时,Javascript包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成功不同的代码块,然
- mapmap(function,iterable)x = [1,2,3,4,5]def square(num): return num*nu
- 一.什么是RedisRedis是一个非关系型数据库,具有很高的存取性能,一般用作缓存数据库,减少正常存储数据库的压力。Redis可以存储键与
- 前言如果我们的应用在启动的时候需要对数据库进行初始化(比如建表等), 可以通过读取.sql文件内容直接执行. 但是, 这样会带出一个问题:在
- 什么是python的迭代如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Ite
- 1、ElementUi文档已经说了,如果需要后端排序,需将sortable设置为custom,同时在 Table 上监听sort-chang
- 本文详细分析了smarty缓存的用法。分享给大家供大家参考。具体分析如下:一开始以为smarty只是用来做一些掩饰php代码功能,但是后来才
- 前言说到 vue 中的 watch 方法,大家可能首先想到,它是用来监听数据的变化,一旦数据发生变化可以执行一些其他的操作。但是 watch
- 本文实例讲述了PHP实现获取第一个中文首字母并进行排序的方法。分享给大家供大家参考,具体如下:最近在做储值结算,需求里结算首页需要按门店的首
- 本文实例讲述了php以post形式发送xml的方法。分享给大家供大家参考。具体方法如下:方法一,使用curl:$xml_data = <
- 最近跑实验,遇到了一个问题:由于实验数据集比较多,每次跑完一个数据集就需要手动更改文件路径,再将文件传到服务器,再运行实验,这样的话效率很低
- 如下所示:data_array = np.loadtxt(filename, #文件名