Go 1.19.4 Sort排序进阶-Day 12
1. 结构体(切片)排序
结构体返回的是切片。
之前学习了sort.Ints()和sort.Strings(),使用这两个sort库下面的方法,可以对int和strings进行排序。
那如果我要对自定义类型进行排序,怎么办,sort库没提供,怎么办?可以参照sort源码自己写一个。
1.1 sort源码解析
一个需要排序的类型,必须要实现下面接口中的3个方法。
type Interface interface {Len() int // 能取长度,不管有多少元素,也不管是什么数据类型
Less(i, j int) bool // 可以取索引,比较大小
Swap(i, j int) // 交换i与j的索引位置
}对于切片来说,Len和Swap都还好处理,难点就在于Less的比较大小。
任意类型或者自定义的类型,如何使用Less进行大小比较呢?我也没有办法提前知道,这个切片中,到底会存放什么类型的元素。
1.1.1 sort.Ints源码解析
sort.Ints(),ctrl+鼠标左键点击ints,会跳转到sort.go,然后会有这样一行代码:
func Ints(x []int) { Sort(IntSlice(x)) },然后ctrl+鼠标左键点击IntSlice,会跳转到这个代码:
type IntSlice []int
func (x IntSlice) Len() int { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x IntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
调用sort.Ints()时,会调用func Ints(x []int) { Sort(IntSlice(x)) },也就是把我们的需要排序的元素,传到IntSlice(x),作用是把元素先转换为自定义IntSlice类型。
对于Len() int { return len(x) }来说,就是取出元素长度。
Swap(i, j int) { x[i], x[j] = x[j], x[i] },主要作用就是交换2个元素的位置。
Less(i, j int) bool { return x[i] < x[j] },比较元素大小,成立返回true,否则返回flase,并进行位置调整,也就是调用Swap方法,也就是默认升序的情况。
1.1.2 sort.Strings源码解析
sort.Strings()
func Strings(x []string) { Sort(StringSlice(x)) }
type StringSlice []string
func (x StringSlice) Len() int { return len(x) }
func (x StringSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x StringSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
可以看到,int和strings的排序实现逻辑,其实是一样的。
1.2 自定义结构体(切片)排序
package mainimport ("fmt""sort"
)type Runner interface {run()
}type Cat struct {name stringage int
}type CatSlice []Cat // 这里就相当于[]Cat{c1, c2, Cat{"Momo", 99}}func (x CatSlice) Len() int { return len(x) }
func (x CatSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x CatSlice) Less(i, j int) bool { return x[i].age < x[j].age }func main() {var c1 = Cat{"Tom", 20}var c2 = Cat{"Jerry", 18}cats := []Cat{c1, c2, Cat{"Momo", 99}}fmt.Println("排序前:", cats)sort.Sort(CatSlice(cats))fmt.Println("排序后:", cats)
}
=========调试结果=========
排序前: [{Tom 20} {Jerry 18} {Momo 99}]
排序后: [{Jerry 18} {Tom 20} {Momo 99}]
1.3 简化版结构体(切片)排序
sort.Slice(),是专门给切片用的。
package mainimport ("fmt""sort"
)type Runner interface {run()
}type Cat struct {name stringage int
}func main() {var c1 = Cat{"Tom", 20}var c2 = Cat{"Jerry", 18}cats := []Cat{c1, c2, Cat{"Momo", 99}}fmt.Println("排序前:", cats)sort.Slice(cats, func(i, j int) bool {return cats[i].age < cats[j].age})fmt.Println("排序后:", cats)
}
=========调试结果=========
排序前: [{Tom 20} {Jerry 18} {Momo 99}]
排序后: [{Jerry 18} {Tom 20} {Momo 99}]
2. map排序
2.1 key排序
2.1.1 升序
package mainimport ("fmt""sort"
)func main() {m := make(map[int]string)m[2] = "abc"m[1] = "xvz"m[100] = "aaa"fmt.Println(m)keys := make([]int, 0, len(m))for k := range m {keys = append(keys, k)}fmt.Println(keys)sort.Ints(keys)fmt.Println(keys)for _, k := range keys {fmt.Println(k, m[k])}
}
=========调试结果=========
map[1:xvz 2:abc 100:aaa]
[2 1 100]
[1 2 100]
1 xvz
2 abc
100 aaa
2.1.2 降序
package mainimport ("fmt""sort"
)func main() {m := make(map[int]string)m[2] = "abc"m[1] = "xvz"m[100] = "aaa"fmt.Println(m)keys := make([]int, 0, len(m))for k := range m {keys = append(keys, k)}fmt.Println(keys)// sort.Ints(keys)sort.Sort(sort.Reverse(sort.IntSlice(keys))) // 调整这里fmt.Println(keys)for _, k := range keys {fmt.Println(k, m[k])}
}
=========调试结果=========
map[1:xvz 2:abc 100:aaa]
[100 2 1]
[100 2 1]
100 aaa
2 abc
1 xvz
2.2 value排序
2.2.1 升序
package mainimport ("fmt""sort"
)type Entry struct {k intv string
}func main() {m := make(map[int]string)m[2] = "abc"m[1] = "xvz"m[100] = "aaa"fmt.Println(m)entries := make([]Entry, 0, len(m))for k, v := range m {entries = append(entries, Entry{k, v})}fmt.Println(entries)sort.Slice(entries, func(i, j int) bool {return entries[i].v < entries[j].v})fmt.Println(entries)
}
=========调试结果=========
map[1:xvz 2:abc 100:aaa]
[{1 xvz} {100 aaa} {2 abc}]
[{100 aaa} {2 abc} {1 xvz}]
3. 排序总结
排序,只支持线性数据结构,如果是hash类型,一定要先转换成线性数据结构。
相关文章:
Go 1.19.4 Sort排序进阶-Day 12
1. 结构体(切片)排序 结构体返回的是切片。 之前学习了sort.Ints()和sort.Strings(),使用这两个sort库下面的方法,可以对int和strings进行排序。 那如果我要对自定义类型进行排序,怎么办,sort库没提供&…...
python-求距离(赛氪OJ)
[题目描述] 给你一个 1−>n 的排列,现在有一次机会可以交换两个数的位置,求交换后最小值和最大值之间的最大距离是多少?输入格式: 输入共两行。 第一行一个数 n 。 第二行 n 个数表示这个排列。输出格式: 输出一行一…...
《第二十一章 传感器与定位 - 传感器应用》
《第二十一章 传感器与定位 - 传感器应用》 在当今的移动应用开发中,充分利用设备的传感器能够为用户带来更加智能和便捷的体验。本章将重点探讨加速度传感器、方向传感器和光线传感器的应用。 一、传感器应用的重要性 随着智能手机和移动设备的普及,传感…...
Windows系统命令
Windows系统命令 Windows 系统中的命令行工具是指令式编程语言,可以用来执行各种任务、管理文件和目录、监控系统状态等。下面是一个 Windows 命令应用实例: 1. 文件操作 cd:用于改变当前目录。例如,cd Documents 将当前目录更…...
C语言函数递归
前言与概述 本文章将通过多个代码并赋予图示,详细讲解C语言函数递归的定义和函数递归的运算过程。 函数递归定义 程序调用自身的编程技巧称为递归。递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。它…...
【python数据分析11】——Pandas统计分析(分组聚合进行组内计算)
分组聚合进行组内计算 前言1、groupby方法拆分数据2、agg方法聚合数据3、apply方法聚合数据4、transform方法聚合数据5 小案例5.1 按照时间对菜品订单详情表进行拆分5.2 使用agg方法计算5.3 使用apply方法统计单日菜品销售数目 前言 依据某个或者几个字段对数据集进行分组&…...
高性能web服务器
目录 一、简介 (一)nginx-高性能的web服务端 (二)用户访问体验 二、I/O模型 (一)概念 (二)网络I/O模型 (三)阻塞型 I/O 模型 (四…...
微服务案例搭建
目录 一、案例搭建 1.数据库表 2.服务模块 二、具体代码实现如下: (1) 首先是大体框架为: (2)父模块中的pom文件配置 (3)shop_common模块,这个模块里面只需要配置pom.xml,与实体…...
SAP负库存
业务示例 在系统中,对于一些物料而言,不能立即将收到的交货输入为收货。如果要使发货无论如何都是可以过帐的,则需要允许这些物料的负库存。 负库存 发货数量大于预订数量时,过帐该发货就会出现负库存。如果由于组织原因&#…...
集团数字化转型方案(三)
集团数字化转型方案通过系统整合人工智能(AI)、大数据、云计算和物联网(IoT)技术,建立了一个全面智能化的业务管理平台,涵盖从业务流程自动化、数据驱动决策支持,到客户体验优化和供应链管理的各…...
ESP32智能设备:蓝牙音箱、AI语音助手、环境监测与调节以及智能控制,基于BLE与MQTT技术(代码详解)
本文将介绍如何实现一个功能丰富的ESP32项目,集成蓝牙音箱、AI语音助手、智能设备控制器、环境监测与调节等功能。通过本项目,您将学习到硬件设计、嵌入式编程、蓝牙技术、音频处理、人工智能与语音识别、物联网平台、数据分析及用户界面构建等技术。 一…...
web渗透测试 学习导图
web渗透学习路线 前言 一、web渗透测试是什么? Web渗透测试分为白盒测试和黑盒测试,白盒测试是指目标网站的源码等信息的情况下对其渗透,相当于代码分析审计。而黑盒测试则是在对该网站系统信息不知情的情况下渗透,以下所说的Web…...
WordPress禁止后台自定义功能
wordpress后台可以彻底禁止主题的自定义菜单功能,下面这段代码添加到functions.php文件中,后台外观菜单中的”自定义”就会消失不见了。 add_filter(map_meta_cap, function($caps, $cap){if($cap customize){return [do_not_allow];}return $caps; },…...
(六)Flink 窗口计算
窗口(Window)是处理无界流的关键所在。窗口可以将数据流装入大小有限的“桶”中,再对每个“桶”加以处理。 目录 时间概念 窗口类型 窗口划分 窗口的生命周期 Window Assigners 窗口函数 Triggers 窗口触发器 Evictor 数据剔除器 Allowed Lateness 旁路输出 时间…...
SQL 布尔盲注 (injection 第六关)
简介 SQL注入(SQL Injection)是一种常见的网络攻击方式,通过向SQL查询中插入恶意的SQL代码,攻击者可以操控数据库,SQL注入是一种代码注入攻击,其中攻击者将恶意的SQL代码插入到应用程序的输入字段中&am…...
OpenAI 重回巅峰:ChatGPT-4O 最新模型超越谷歌 Gemini 1.5,多项测试夺冠!
谷歌上周发布的Gemini 1.5 Pro模型,在LMSYS办的聊天机器人竞技场Chatbot Arena中获得第一名。但是,OpenAI迅速反应,推出了最新的chatgpt-4o-latest模型,重新夺回了冠军头衔。 chatgpt-4o-latest模型简介 OpenAI最近推出了名为gpt-…...
软件工程(2)面向对象方法:Booch方法与开发实例
Booch方法(Booch Method)是由Grady Booch提出的一种面向对象的软件开发方法。它是一种系统分析与设计的框架,主要用于设计和建模面向对象的系统。Booch方法特别关注对象模型的构建,以及类、对象和它们之间的关系。以下是Booch方法…...
高阶面试-concurrentHashMap的整理
算不上死磕,里面太痛苦了,现在很多位移等操作还看不懂,只是先理清大致思路,面试用 concurrentHashMap的实现原理 为啥会用到?并发安全。之前都用的hashtable实现线程安全的map,但是太过笨重,不…...
VSCode系列 - 如何用VSCode搭建C++高效开发环境(1)
VSCode是笔者用过的最好用的开发工具,没有之一。笔者14年的码龄生涯中,先后用过Eclipse、 IntelliJ IDEA、 WebStorm、 PyCharm、 Visual Studio(2010/2013/2015)、 NetBeans、 Sublime Text等,但自从用VSCode之后,就再没换过其他…...
【人工智能】Python融合机器学习、深度学习和微服务的创新之路
1. 🚀 引言1.1 🚀 人工智能的现状与发展趋势1.2 📜 机器学习、深度学习和神经网络的基本概念1.3 🏆 微服务架构在人工智能中的作用 2. 🔍 机器学习的演变与创新2.1 🌟 机器学习的历史回顾2.2 🧠…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
