Go高级特性探究之稳定排序详解
作者:tracy小猫 发布时间:2023-07-17 16:11:48
标签:Go,排序
在 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
0
投稿
猜你喜欢
- 最近有Win10系统用户反映,由于自己的电脑安装有两个python软件,所以想要卸载掉其中一个,不过在卸载的时候却发现无法卸载,并且出现提示
- '*************************************************'函数名:getMaxO
- 如何使用Index Server建立一个网站导航地图?程序代码如下:<html><head><title>asp教程之网站导航 -
- lambda函数是一种小的匿名函数。lambda语法lambda函数:lambda [arg1 [,arg2,...[,argn]]] :
- 可能各位朋友看到这个标题很不解,到底什么是习惯化,什么又是去习惯化?下面我来慢慢介绍我的个人理论。习惯化:随着对刺激的熟悉,人们越来越注意不
- 见下面的代码:<html><head><title>精彩春风之月份查询</title><
- 首先看一下这三个函数:rtrim() ltrim() trim();rtrim()定义以及用法: rtrim() 函数移除字符串右侧的空白字
- 网页上的图片如果设置了alt属性,当鼠标移经时就会有tooltip出现,但是只能显示一行文本,有时需要多行文本,乃至图片来显示图片、链接或者
- 我开发过几个采集程序,也研究过很多采集程序代码,所以对采集程序的原理还算是稍微有些了解。先说一下采集原理:采集程序的主要步骤如下: 一、获取
- 核心代码function convert2utf8($string) { return iconv(&
- 我是从去年初开始学习web标准的,两年下来也有些心得。最近跳槽了正好闲在家里,写一些出来和大家交流一下。1对于web标准和W3C XHTML
- (1)OracleServiceSID 数据库服务,这个服务会自动地启动和停止数据库。如果安装了一个数据库,它的缺省启动类型为自动。服务进程
- 呵,以前也没考虑过这方面的东西,现在写的代码越来越多,越来越复杂,如果再不把不用的变量及时释放掉,到时肯定会出问题。今天无意中在无忧Q群里看
- 如果你正在负责一个基于SQL Server的项目,或者你刚刚接触SQL Server,你都有可能要面临一些数据库性能的问题,这篇文章会为你提
- PHP 异常处理异常用于在指定的错误发生时改变脚本的正常流程。异常是什么异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程。这种情
- SQL语句更改表所有者SQL语句更改表所有者单个修改所有者sql语句如下:查询分析器输入:EXEC sp_changeobject
- 说明:这个例子,首先是把SPAN里的内容用display:none;干掉,就是不显示; 然后在A:HOVER时,再把SPAN里的内容disp
- 在Oracle SQL的where子句中传入字符类型参数'19-11月-08',使得可以直接和日期类型比较,或者转换一下同日
- 各位想必都知道,onfocus="this.blur()"这条代码能消除链接时的虚线框,但你有没有想过,如果你的网页上有
- 运行代码框<HTML><HEAD><title>漂亮的下拉框</title><meta