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
写在前面的使用总结: 排序结构体 实现Len,Less,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发送邮件有很多的实现方式 第一种:Java 原生发邮件mail.jar和activation.jar <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency><groupId>jav…...
CNI 网络流量分析(六)Calico 介绍与原理(二)
文章目录CNI 网络流量分析(六)Calico 介绍与原理(二)CNIIPAM指定 IP指定非 IPAM IPCNI 网络流量分析(六)Calico 介绍与原理(二) CNI 支持多种 datapath,默认是 linuxDa…...
短视频标题的几种类型和闭坑注意事项
目录 短视频标题的几种类型 1、悬念式 2、蹭热门式 3、干货式 4、对比式方法 5、总分/分总式方法 6、挑战式方式 7、启发激励式 8、讲故事式 02注意事项 1、避免使用冷门、生僻词汇 标题是点睛之笔,核心是视频内容 短视频标题的几种类型 1、悬念式 通过…...

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

【html弹框拖拽和div拖拽功能】原生html页面引入vue语法后通过自定义指令简单实现div和弹框拖拽功能
前言 这是html版本的。只是引用了vue的语法。 这是很多公司会出现的一种情况,就是原生的页面,引入vue的语法开发 这就导致有些vue上很简单的功能。放到这里需要转换一下 以前写过一个vue版本的帖子,现在再加一个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 为什么要降维?2 主成分分析原理3 PCA与SVD的联系4 Python实现0 写在前面 机器学习强基计划聚焦深度和广度,加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理;“广”在分析多个机器学习模型…...

Hudi-集成Spark之spark-shell 方式
Hudi集成Spark之spark-shell 方式 启动 spark-shell (1)启动命令 #针对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之字符串精讲(下)
前言 今天继续讲解字符串下半部分,内容包括字符串的检索、大小写转换、去除字符串中空格和特殊字符。 一、检索字符串 在Python中,字符串对象提供了很多用于字符串查找的方法,主要给大家介绍以下几种方法。 1. count() 方法 count() 方法…...

Python图像卡通化animegan2-pytorch实例演示
先看下效果图: 左边是原图,右边是处理后的图片,使用的 face_paint_512_v2 模型。 项目获取: animegan2-pytorch 下载解压后 cmd 可进入项目地址的命令界面。 其中 img 是我自己建的,用于存放图片。 需要 torch 版本 …...

谢希仁版《计算机网络》期末总复习【完结】
文章目录说明第一章 计算机网络概述计算机网络和互联网网络边缘网络核心分组交换网的性能网络体系结构控制平面和数据平面第二章 IP地址分类编址子网划分无分类编址特殊用途的IP地址IP地址规划和分配第三章 应用层应用层协议原理万维网【URL / HTML / HTTP】域名系统DNS动态主机…...
问:React的useState和setState到底是同步还是异步呢?
先来思考一个老生常谈的问题,setState是同步还是异步? 再深入思考一下,useState是同步还是异步呢? 我们来写几个 demo 试验一下。 先看 useState 同步和异步情况下,连续执行两个 useState 示例 function Component() {const…...

深度理解机器学习16-门控循环单元
评估简单循环神经网络的缺点。 描述门控循环单元(Gated Recurrent Unit,GRU)的架构。 使用GRU进行情绪分析。 将GRU应用于文本生成。 基本RNN通常由输入层、输出层和几个互连的隐藏层组成。最简单的RNN有一个缺点,那就是它们不…...
Python中Generators教程
要想创建一个iterator,必须实现一个有__iter__()和__next__()方法的类,类要能够跟踪内部状态并且在没有元素返回的时候引发StopIteration异常. 这个过程很繁琐而且违反直觉.Generator能够解决这个问题. python generator是一个简单的创建iterator的途径…...
数据结构与算法基础-学习-10-线性表之栈的清理、销毁、压栈、弹栈
一、函数实现1、ClearSqStack(1)用途清理栈的空间。只需要栈顶指针和栈底指针相等,就说明栈已经清空,后续新入栈的数据可以直接覆盖,不用实际清理数据,提升了清理效率。(2)源码Statu…...

Leetcode 每日一题 1234. 替换子串得到平衡字符串
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...