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
投稿
猜你喜欢
- 1.现在我本机系统已内置python2.62.下载进行源码安装复制链接下载到/root/mypackage,解压接着mkdir /usr/l
- 常见面试题Vue 如何监控数组defineProperty 真的不能监测数组变化吗?Vue 是如何追踪数据发生变化在 Vue 中当我们把一个
- 项目有时要用一些Ajax的效果,因为比较简单,也就没有去用什么Ajax.net之类的东西,手写代码也就实现了。、第二天,有人反馈错误;说是只
- 1、 数据库闭包表简介像MySQL这样的关系型数据库,比较适合存储一些类似表格的扁平化数据,但是遇到像树形结构这样有深度的数据,就很难驾驭了
- 论文:Interactive Image Warping(1993年Andreas Gustafsson)算法思路:以眼睛中心为中心点,对眼
- MySQL和MariaDB的关系MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。MariaDB
- 说明1、导入unittest模块。2、导入被测对象。3、创建测试类unittest.TestCase。4、重写setUp和tearDown(
- 在一篇文章 理解Python异步编程的基本原理 这篇文章中,我们讲到,如果在异步代码里面又包含了一段非常耗时的同步代码,异步代码就会被卡住。
- 调用jupyter notebook文件内的函数一种简单方法python开发环境jupyter notebook良好的交互式和模块化受到很多
- 本文实例讲述python调用Moxa PCOMM Lite通过串口Ymodem协议实现发送文件的方法,该程序采用python 2.7编写。主
- 超级简单实现iframe框架滚动控制,前提要会简单修改原代码。step1:插入iframe标签在你想要的位置。<iframe 
- 磁盘搜索是性能的很大瓶颈。这个问题在数据大量增长以至于无法使用有效的缓存时尤为明显。或多或少随即访问大数据库时,就必然会有至少一次磁盘搜索来
- 本文实现文件分类器的目的主要是为了将办公过程中产生的各种格式的文件完成整理。通过自定义需要整理的文件目录,将该目录下面的全部文件按照文件格式
- PHP ZipArchive 是PHP自带的扩展类,可以轻松实现ZIP文件的压缩和解压,使用前首先要确保PHP ZIP 扩展已经开启,具体开
- 一、Pyecharts 概述Pyechart 是一个用于生成 Echarts 图表(Echarts 是基于 Javascript 的开源可视
- var InterestKeywordListString = $("#userInterestKeywordLabel"
- 本文实例讲述了flask框架jinja2模板与模板继承。分享给大家供大家参考,具体如下:jinja2模板from werkzeug.cont
- 前言前段时间9月21日参加了在成都举办的第五届FEDAY, 印象比较深刻的是白鹭引擎首席架构师@王泽分享的《框架开发中的基础设施搭建》 ,提
- git checkout . #本地所有修改的。没有的提交的,都返回到原来的状态git stash #把所有没有提交的修改暂存到stash里
- 斜角导航条看上去立体感比较强,但实现起来比较麻烦;这是前几天写的一个测试代码,实现时,本来想用简单的图片加负数来实现;但GIF图片对半透明的