Go高级特性探究之稳定排序详解
作者:tracy小猫 时间:2023-07-17 16:11:48
在 IT 开发中,有时我们需要对结构体数组进行排序。Go 语言提供了 sort 包,其中最常用的一种是 sort.Slice() 函数。但是,当我们需要保持相同元素之间的顺序稳定时,该如何实现呢?
本篇文章将为大家介绍如何使用 sort.SliceStable() 对结构体数组的某个字段进行稳定排序。同时,我们将为你展示如何使用反射和结构体标签,让排序更加优雅和通用。
给结构体字段打上“排序标签”
如果我们有一个名为 Student
的结构体,其中包含了一个 Name
字符串字段,我们希望对 Student 数组按照 Name 字段进行排序,该怎么办呢?我们可以为 Name 字段打上一个“排序标签”,表示排序时使用的顺序:
type Student struct {
Id int sort:"id"
Name string sort:"name"
Score float64 sort:"score"
}
使用 sort.SliceStable() 进行稳定排序
接下来,我们将展示一个可适用于任何类型的排序函数。该函数将通过反射和标签获取结构体的排序字段,并使用 sort.SliceStable() 进行排序。
func SortSliceStable(slice interface{}, sortField string) {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
panic("SortSliceStable called with non-slice type")
}
if rv.Len() == 0 {
return
}
// 获取结构体的元素类型
elemType := rv.Type().Elem()
// 获取排序字段
field, ok := elemType.FieldByName(sortField)
if !ok {
panic("SortSliceStable called with unknown or unexported struct field name: " + sortField)
}
// 获取 less 函数
less := func(i, j int) bool {
v1 := rv.Index(i).FieldByName(field.Name)
v2 := rv.Index(j).FieldByName(field.Name)
switch v1.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v1.Int() < v2.Int()
case reflect.Float32, reflect.Float64:
return v1.Float() < v2.Float()
case reflect.String:
return v1.String() < v2.String()
}
panic("unsupported type")
}
// 使用 sort.SliceStable 进行排序
sort.SliceStable(slice, less)
}
现在,我们可以按照以下方法使用该排序函数进行排序:
func main() {
students := []Student{
{1, "zhangsan", 90.0},
{2, "lisi", 80.0},
{3, "wangwu", 70.0},
}
// 按照 Name 字段进行排序
SortSliceStable(students, "name")
fmt.Println(students)
}
运行以上代码,即可得到按照 Name 字段进行稳定排序的结果:
[{2 lisi 80} {3 wangwu 70} {1 zhangsan 90}]
通过添加标签和使用反射,我们让排序过程更加通用和优雅。这个方法能够有效地提高我们的工作效率和代码质量,值得我们推广和应用。稳定排序,原来这么简单!
来源:https://juejin.cn/post/7238570834342805563
标签:Go,排序
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
python协程之动态添加任务的方法
2021-03-24 04:27:54
![](https://img.aspxhome.com/file/2023/5/131365_0s.jpg)
该死的IE,走好
2009-01-15 12:26:00
![](https://img.aspxhome.com/file/UploadPic/20091/15/byebye_ie6-71s.png)
python合并文本文件示例
2021-05-08 01:24:49
好用的VSCode头部注释插件Fileheader Pro
2023-07-05 06:16:00
python做接口测试的必要性
2022-06-09 00:05:41
Centos7.3下mysql5.7.18安装并修改初始密码的方法
2024-01-20 00:02:11
![](https://img.aspxhome.com/file/2023/9/105669_0s.jpg)
PHP多种序列化/反序列化的方法详解
2024-04-30 08:47:55
ORACLE分区表转换在线重定义DBMS_REDEFINITION
2024-01-16 00:23:18
通过实例简单了解Python sys.argv[]使用方法
2022-09-12 14:14:35
![](https://img.aspxhome.com/file/2023/4/113004_0s.png)
Python7个爬虫小案例详解(附源码)下篇
2023-11-23 03:47:38
![](https://img.aspxhome.com/file/2023/7/86647_0s.png)
PHP APC缓存配置、使用详解
2023-11-21 22:15:15
前端token中4个存储位置的优缺点说明
2023-07-02 16:39:50
哪种Python框架适合你?简单介绍几种主流Python框架
2023-04-27 03:21:52
三分钟时间教你用Python绘制春联
2023-11-06 00:26:08
![](https://img.aspxhome.com/file/2023/9/115759_0s.jpg)
Python字节单位转换实例
2023-07-18 07:09:16
python的dataframe转换为多维矩阵的方法
2021-08-19 08:59:09
![](https://img.aspxhome.com/file/2023/9/131399_0s.jpg)
向外扩展SQL Server 实现更高扩展性
2008-12-18 14:45:00
虚拟环境及venv和virtualenv的区别说明
2021-07-07 09:19:51
Pycharm之如何安装cv2 [python3.6]
2023-01-15 09:56:45
![](https://img.aspxhome.com/file/2023/7/69427_0s.png)
Python yield生成器和return对比代码实例
2022-07-17 21:54:57