当前位置: 首页 > news >正文

Go 排序包 sort

写在前面的使用总结:

排序结构体

实现Len,Less,Swap三个函数

package main  import (  "fmt"  "sort")  type StuScore struct {  name  string  score int  
}  type StuScores []StuScore  func (s StuScores) Len() int {  return len(s)  
}  func (s StuScores) Less(i, j int) bool {  return s[i].score < s[j].score  
}  func (s StuScores) Swap(i, j int) {  s[i], s[j] = s[j], s[i]  
}  func main() {  stus := StuScores{  {"mike ", 98},  {"jj", 91},  {"hello", 96},  {"simple", 90},  }  fmt.Println("Default:\n\t", stus)  sort.Sort(stus)  fmt.Println("IS sorted?\n\t", sort.IsSorted(stus))  fmt.Println("Sorted:\n\t", stus)  
}

排序int切片

s := []int{5, 2, 6, 3, 1, 4} // 未排序的切片数据
sort.Ints(s)
fmt.Println(s) // 将会输出[1 2 3 4 5 6]

排序float64切片

Float := []float64{1.2, 3.4, 8.2, 1.1}  sort.Float64s(Float)  
fmt.Println(Float) //[1.1 1.2 3.4 8.2]  
fmt.Println(sort.Float64sAreSorted(Float))//true  
fmt.Println(sort.SearchFloat64s(Float, 1.2))// 1

排序string切片

Strings := []string{"1", "4", "a", "0", "2"}  sort.Strings(Strings)  
fmt.Println(Strings)  
fmt.Println(sort.StringsAreSorted(Strings))  
fmt.Println(sort.SearchStrings(Strings, "a"))  /*  
[0 1 2 4 a]  
true  
4  
*/

简介

基本实现了插入排序,归并排序,堆排序和快速排序。当然这四种排序方法是不分开的,它们是在sort包的内部被使用。所以使用时,不用考虑使用那种排序方法。
sort会自动选择合适的排序方法保证高效性。

使用:

只要实现了 sort.Interface 定义的三个方法:获取数据集合长度的 Len() 方法、比较两个元素大小的 Less() 方法和交换两个元素位置的 Swap() 方法,就可以顺利对数据集合进行排序。

数据集合排序

前面说了,对数据集合排序(包括自定义数据类型集合)排序需要实现sort.Interface接口的三个方法,我们看看该接口的定义:

type Interface interface{//获取数据集合元素个数Len() int//如果i索引的数据小于j索引的数据,返回true,且不会调用下面的Swap(),即数据升序排序Less(i,j int) bool //交换i和j索引的两个元素的位置Swap(i,j int )}

数据集合实现了这三个方法后,即可调用该包的Sort()方法进行排序,Sort()方法定义如下:

func Sort(data Interface)

Sort()方法唯一的参数就是带排序的数据集合
该包还提供了一个方法可以判断数据集合是否已经排好了顺序,该方法的内部实现依赖于我们自己实现的Len()和Less()方法:

func IsSorted(data Interface) bool {n := data.Len()for i := n - 1; i > 0; i-- {if data.Less(i, i-1) {return false}}return true
}

下面是一个使用sort包对学生成绩进行排序的实例:

package main  import (  "fmt"  "sort")  type StuScore struct {  name  string  score int  
}  type StuScores []StuScore  func (s StuScores) Len() int {  return len(s)  
}  func (s StuScores) Less(i, j int) bool {  return s[i].score < s[j].score  
}  func (s StuScores) Swap(i, j int) {  s[i], s[j] = s[j], s[i]  
}  func main() {  stus := StuScores{  {"mike ", 98},  {"jj", 91},  {"hello", 96},  {"simple", 90},  }  fmt.Println("Default:\n\t", stus)  sort.Sort(stus)  fmt.Println("IS sorted?\n\t", sort.IsSorted(stus))  fmt.Println("Sorted:\n\t", stus)  
}

该示例实现的是升序排序,如果要得到降序排序结果,其实只要修改 Less() 函数:

//Less(): 成绩降序排序 , 只将小于号修改为大于号
func (s StuScores) Less(i, j int) bool {return s[i].score > s[j].score
}

此外,sort包提供了 Reverse() 方法,可以允许将数据按 Less() 定义的排序方式逆序排序,而不必修改 Less() 代码。方法定义如下:

func Reverse(data Interface) Interface

我们可以看到 Reverse() 返回的一个 sort.Interface 接口类型,整个 Reverse() 的内部实现比较有趣:

// 定义了一个 reverse 结构类型,嵌入 Interface 接口
type reverse struct {Interface
}//reverse 结构类型的 Less() 方法拥有嵌入的 Less() 方法相反的行为
//Len() 和 Swap() 方法则会保持嵌入类型的方法行为
func (r reverse) Less(i, j int) bool {return r.Interface.Less(j, i)
}// 返回新的实现 Interface 接口的数据类型
func Reverse(data Interface) Interface {return &reverse{data}
}

了解内部原理后,可以在学生成绩排序示例中使用 Reverse() 来实现成绩升序排序:

sort.Sort(sort.Reverse(stus))
fmt.Println(stus)

最后一个方法Search()

func Search(n int,f func(int)bool) int

该方法会使用“二分查找”算法来找出能使 f(x)(0<=x<n) 返回 ture 的最小值 i。 前提条件 : f(x)(0<=x<i) 均返回 false, f(x)(i<=x<n) 均返回 ture。 如果不存在 i 可以使 f(i) 返回 ture, 则返回 n。

Search() 函数一个常用的使用方式是搜索元素 x 是否在已经升序排好的切片 s 中:

x := 11
s := []int{3, 6, 8, 11, 45} // 注意已经升序排序
pos := sort.Search(len(s), func(i int) bool { return s[i] >= x })
if pos < len(s) && s[pos] == x {fmt.Println(x, " 在 s 中的位置为:", pos)
} else {fmt.Println("s 不包含元素 ", x)
}

官方文档还给出了一个猜数字的小程序:

func GuessingGame() {var s stringfmt.Printf("Pick an integer from 0 to 100.\n")answer := sort.Search(100, func(i int) bool {fmt.Printf("Is your number <= %d? ", i)fmt.Scanf("%s", &s)return s != "" && s[0] == 'y'})fmt.Printf("Your number is %d.\n", answer)
}

sort包对于内部数据类型的排序

sort包原生支持[]int,[]float64,[]string三种内建数据类型切片的排序操作,我们不用自己实现Len(),Less(),Swap()方法

IntSlice类型及[]int排序

由于[]int切片排序内部实现及使用方法和[]float64,[]string类似,这里就描述其中一部分。

sort排序IntSlice类型,并且实现sort.Interface 接口。

type IntSlice []int
func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
//IntSlice 类型定义了 Sort() 方法,包装了 sort.Sort() 函数
func (p IntSlice) Sort() { Sort(p) }
//IntSlice 类型定义了 SearchInts() 方法,包装了 SearchInts() 函数
func (p IntSlice) Search(x int) int { return SearchInts(p, x) }

并且提供了sort.Ints()方法使用了该IntSlice类型:

func Ints(a []int){Sort(IntSlice(a)) } 

使用对[]int切片进行排序更常使用sort.Ints(),而不是IntSlice类型:

s := []int{5, 2, 6, 3, 1, 4} // 未排序的切片数据
sort.Ints(s)
fmt.Println(s) // 将会输出[1 2 3 4 5 6]

如果要使用降序排序,显然要用前面提到的 Reverse() 方法:

s := []int{5, 2, 6, 3, 1, 4} // 未排序的切片数据
sort.Sort(sort.Reverse(sort.IntSlice(s)))
fmt.Println(s) // 将会输出[6 5 4 3 2 1]

如果要查找整数 x 在切片 a 中的位置,相对于前面提到的 Search() 方法,sort包提供了 SearchInts():

func SearchInts(a []int, x int) int

注意,SearchInts() 的使用条件为:切片 a 已经升序排序 以下是一个错误使用的例子:

s := []int{5, 2, 6, 3, 1, 4} // 未排序的切片数据
fmt.Println(sort.SearchInts(s, 2)) // 将会输出 0 而不是 1

Float64Slice类型和[]float64排序

实现与 Ints 类似,只看一下其内部实现:

type Float64Slice []float64func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
func (p Float64Slice) Sort() { Sort(p) }
func (p Float64Slice) Search(x float64) int { return SearchFloat64s(p, x) }

与 Sort()、IsSorted()、Search() 相对应的三个方法:

func Float64s(a []float64)  
func Float64sAreSorted(a []float64) bool
func SearchFloat64s(a []float64, x float64) int

要说明一下的是,在上面 Float64Slice 类型定义的 Less 方法中,有一个内部函数 isNaN()。 isNaN() 与_math_包中 IsNaN() 实现完全相同,sort包之所以不使用 math.IsNaN(),完全是基于包依赖性的考虑,应当看到,sort包的实现不依赖与其他任何包。

StringSlice 类型及[]string 排序

两个 string 对象之间的大小比较是基于“字典序”的。

实现与 Ints 类似,只看一下其内部实现:

type StringSlice []stringfunc (p StringSlice) Len() int           { return len(p) }
func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p StringSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
func (p StringSlice) Sort() { Sort(p) }
func (p StringSlice) Search(x string) int { return SearchStrings(p, x) }

与 Sort()、IsSorted()、Search() 相对应的三个方法:

func Strings(a []string)
func StringsAreSorted(a []string) bool
func SearchStrings(a []string, x string) int

相关文章:

Go 排序包 sort

写在前面的使用总结&#xff1a; 排序结构体 实现Len&#xff0c;Less&#xff0c;Swap三个函数 package main import ( "fmt" "sort") type StuScore struct { name string score int } type StuScores []StuScore func (s StuScores) Len(…...

Java Email 发HTML邮件工具 采用 freemarker模板引擎渲染

Java Email 发HTML邮件工具 采用 freemarker模板引擎 1.常用方式对比 Java发送邮件有很多的实现方式 第一种&#xff1a;Java 原生发邮件mail.jar和activation.jar <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency><groupId>jav…...

CNI 网络流量分析(六)Calico 介绍与原理(二)

文章目录CNI 网络流量分析&#xff08;六&#xff09;Calico 介绍与原理&#xff08;二&#xff09;CNIIPAM指定 IP指定非 IPAM IPCNI 网络流量分析&#xff08;六&#xff09;Calico 介绍与原理&#xff08;二&#xff09; CNI 支持多种 datapath&#xff0c;默认是 linuxDa…...

短视频标题的几种类型和闭坑注意事项

目录 短视频标题的几种类型 1、悬念式 2、蹭热门式 3、干货式 4、对比式方法 5、总分/分总式方法 6、挑战式方式 7、启发激励式 8、讲故事式 02注意事项 1、避免使用冷门、生僻词汇 标题是点睛之笔&#xff0c;核心是视频内容 短视频标题的几种类型 1、悬念式 通过…...

操作系统——1.操作系统的概念、定义和目标

目录 1.概念 1.1 操作系统的种类 1.2电脑的组成 1.3电脑组成的介绍 1.4操作系统的概念&#xff08;定义&#xff09; 2.操作系统的功能和目标 2.1概述 2.2 操作系统作为系统资源的管理者 2.3 操作系统作为用户和计算机硬件间的接口 2.3.1用户接口的解释 2.3.2 GUI 2.3.3接…...

【html弹框拖拽和div拖拽功能】原生html页面引入vue语法后通过自定义指令简单实现div和弹框拖拽功能

前言 这是html版本的。只是引用了vue的语法。 这是很多公司会出现的一种情况&#xff0c;就是原生的页面&#xff0c;引入vue的语法开发 这就导致有些vue上很简单的功能。放到这里需要转换一下 以前写过一个vue版本的帖子&#xff0c;现在再加一个html版本的。 另一个vue版本…...

2023新华为OD机试题 - 计算网络信号(JavaScript) | 刷完必过

计算网络信号 题目 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。 注意:网络信号可以绕过阻隔物 array[m][n] 的二维数组代表网格地图,array[i][j] = 0代表 i 行 j 列是空旷位置;array[i][j] = x(x 为正整数)代表 i 行 …...

27.边缘系统的架构

文章目录27 Architecures for the Edge 边缘系统的架构27.1 The Ecosystem of Edge-Dominant Systems 边缘主导系统的生态系统27.2 Changes to the Software Development Life Cycle 软件开发生命周期的变化27.3 Implications for Architecture 对架构的影响27.4 Implications …...

机器学习强基计划8-1:图解主成分分析PCA算法(附Python实现)

目录0 写在前面1 为什么要降维&#xff1f;2 主成分分析原理3 PCA与SVD的联系4 Python实现0 写在前面 机器学习强基计划聚焦深度和广度&#xff0c;加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理&#xff1b;“广”在分析多个机器学习模型&#xf…...

Hudi-集成Spark之spark-shell 方式

Hudi集成Spark之spark-shell 方式 启动 spark-shell &#xff08;1&#xff09;启动命令 #针对Spark 3.2 spark-shell \--conf spark.serializerorg.apache.spark.serializer.KryoSerializer \--conf spark.sql.catalog.spark_catalogorg.apache.spark.sql.hudi.catalog.Hoo…...

Python爬虫:从js逆向了解西瓜视频的下载链接的生成

前言 最近花费了几天时间,想获取西瓜视频这个平台上某个视频的下载链接,运用js逆向进行获取。其实,如果小编一开始就注意到这一点(就是在做js逆向时,打了断点之后,然后执行相关代码,查看相关变量的值,结果一下子就蹦出很多视频相关的数据,查看了网站下的相关api链接,也…...

Numpy-如何对数组进行切割

前言 本文是该专栏的第24篇,后面会持续分享python的数据分析知识,记得关注。 继上篇文章,详细介绍了使用numpy对数组进行叠加。本文再详细来介绍,使用numpy如何对数组进行切割。说句题外话,前面有重点介绍numpy的各个知识点。 感兴趣的同学,可查看笔者之前写的详细内容…...

Python之字符串精讲(下)

前言 今天继续讲解字符串下半部分&#xff0c;内容包括字符串的检索、大小写转换、去除字符串中空格和特殊字符。 一、检索字符串 在Python中&#xff0c;字符串对象提供了很多用于字符串查找的方法&#xff0c;主要给大家介绍以下几种方法。 1. count() 方法 count() 方法…...

Python图像卡通化animegan2-pytorch实例演示

先看下效果图&#xff1a; 左边是原图&#xff0c;右边是处理后的图片&#xff0c;使用的 face_paint_512_v2 模型。 项目获取&#xff1a; animegan2-pytorch 下载解压后 cmd 可进入项目地址的命令界面。 其中 img 是我自己建的&#xff0c;用于存放图片。 需要 torch 版本 …...

谢希仁版《计算机网络》期末总复习【完结】

文章目录说明第一章 计算机网络概述计算机网络和互联网网络边缘网络核心分组交换网的性能网络体系结构控制平面和数据平面第二章 IP地址分类编址子网划分无分类编址特殊用途的IP地址IP地址规划和分配第三章 应用层应用层协议原理万维网【URL / HTML / HTTP】域名系统DNS动态主机…...

问:React的useState和setState到底是同步还是异步呢?

先来思考一个老生常谈的问题&#xff0c;setState是同步还是异步? 再深入思考一下&#xff0c;useState是同步还是异步呢&#xff1f; 我们来写几个 demo 试验一下。 先看 useState 同步和异步情况下&#xff0c;连续执行两个 useState 示例 function Component() {const…...

深度理解机器学习16-门控循环单元

评估简单循环神经网络的缺点。 描述门控循环单元&#xff08;Gated Recurrent Unit&#xff0c;GRU&#xff09;的架构。 使用GRU进行情绪分析。 将GRU应用于文本生成。 基本RNN通常由输入层、输出层和几个互连的隐藏层组成。最简单的RNN有一个缺点&#xff0c;那就是它们不…...

Python中Generators教程

要想创建一个iterator&#xff0c;必须实现一个有__iter__()和__next__()方法的类&#xff0c;类要能够跟踪内部状态并且在没有元素返回的时候引发StopIteration异常. 这个过程很繁琐而且违反直觉.Generator能够解决这个问题. python generator是一个简单的创建iterator的途径…...

数据结构与算法基础-学习-10-线性表之栈的清理、销毁、压栈、弹栈

一、函数实现1、ClearSqStack&#xff08;1&#xff09;用途清理栈的空间。只需要栈顶指针和栈底指针相等&#xff0c;就说明栈已经清空&#xff0c;后续新入栈的数据可以直接覆盖&#xff0c;不用实际清理数据&#xff0c;提升了清理效率。&#xff08;2&#xff09;源码Statu…...

Leetcode 每日一题 1234. 替换子串得到平衡字符串

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...