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

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. 结构体&#xff08;切片&#xff09;排序 结构体返回的是切片。 之前学习了sort.Ints()和sort.Strings()&#xff0c;使用这两个sort库下面的方法&#xff0c;可以对int和strings进行排序。 那如果我要对自定义类型进行排序&#xff0c;怎么办&#xff0c;sort库没提供&…...

python-求距离(赛氪OJ)

[题目描述] 给你一个 1−>n 的排列&#xff0c;现在有一次机会可以交换两个数的位置&#xff0c;求交换后最小值和最大值之间的最大距离是多少&#xff1f;输入格式&#xff1a; 输入共两行。 第一行一个数 n 。 第二行 n 个数表示这个排列。输出格式&#xff1a; 输出一行一…...

《第二十一章 传感器与定位 - 传感器应用》

《第二十一章 传感器与定位 - 传感器应用》 在当今的移动应用开发中&#xff0c;充分利用设备的传感器能够为用户带来更加智能和便捷的体验。本章将重点探讨加速度传感器、方向传感器和光线传感器的应用。 一、传感器应用的重要性 随着智能手机和移动设备的普及&#xff0c;传感…...

Windows系统命令

Windows系统命令 Windows 系统中的命令行工具是指令式编程语言&#xff0c;可以用来执行各种任务、管理文件和目录、监控系统状态等。下面是一个 Windows 命令应用实例&#xff1a; 1. 文件操作 cd&#xff1a;用于改变当前目录。例如&#xff0c;cd Documents 将当前目录更…...

C语言函数递归

前言与概述 本文章将通过多个代码并赋予图示&#xff0c;详细讲解C语言函数递归的定义和函数递归的运算过程。 函数递归定义 程序调用自身的编程技巧称为递归。递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。它…...

【python数据分析11】——Pandas统计分析(分组聚合进行组内计算)

分组聚合进行组内计算 前言1、groupby方法拆分数据2、agg方法聚合数据3、apply方法聚合数据4、transform方法聚合数据5 小案例5.1 按照时间对菜品订单详情表进行拆分5.2 使用agg方法计算5.3 使用apply方法统计单日菜品销售数目 前言 依据某个或者几个字段对数据集进行分组&…...

高性能web服务器

目录 一、简介 &#xff08;一&#xff09;nginx-高性能的web服务端 &#xff08;二&#xff09;用户访问体验 二、I/O模型 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;网络I/O模型 &#xff08;三&#xff09;阻塞型 I/O 模型 &#xff08;四&#xf…...

微服务案例搭建

目录 一、案例搭建 1.数据库表 2.服务模块 二、具体代码实现如下&#xff1a; (1) 首先是大体框架为&#xff1a; &#xff08;2&#xff09;父模块中的pom文件配置 &#xff08;3&#xff09;shop_common模块&#xff0c;这个模块里面只需要配置pom.xml&#xff0c;与实体…...

SAP负库存

业务示例 在系统中&#xff0c;对于一些物料而言&#xff0c;不能立即将收到的交货输入为收货。如果要使发货无论如何都是可以过帐的&#xff0c;则需要允许这些物料的负库存。 负库存 发货数量大于预订数量时&#xff0c;过帐该发货就会出现负库存。如果由于组织原因&#…...

集团数字化转型方案(三)

集团数字化转型方案通过系统整合人工智能&#xff08;AI&#xff09;、大数据、云计算和物联网&#xff08;IoT&#xff09;技术&#xff0c;建立了一个全面智能化的业务管理平台&#xff0c;涵盖从业务流程自动化、数据驱动决策支持&#xff0c;到客户体验优化和供应链管理的各…...

ESP32智能设备:蓝牙音箱、AI语音助手、环境监测与调节以及智能控制,基于BLE与MQTT技术(代码详解)

本文将介绍如何实现一个功能丰富的ESP32项目&#xff0c;集成蓝牙音箱、AI语音助手、智能设备控制器、环境监测与调节等功能。通过本项目&#xff0c;您将学习到硬件设计、嵌入式编程、蓝牙技术、音频处理、人工智能与语音识别、物联网平台、数据分析及用户界面构建等技术。 一…...

web渗透测试 学习导图

web渗透学习路线 前言 一、web渗透测试是什么&#xff1f; Web渗透测试分为白盒测试和黑盒测试&#xff0c;白盒测试是指目标网站的源码等信息的情况下对其渗透&#xff0c;相当于代码分析审计。而黑盒测试则是在对该网站系统信息不知情的情况下渗透&#xff0c;以下所说的Web…...

WordPress禁止后台自定义功能

wordpress后台可以彻底禁止主题的自定义菜单功能&#xff0c;下面这段代码添加到functions.php文件中&#xff0c;后台外观菜单中的”自定义”就会消失不见了。 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注入&#xff08;SQL Injection&#xff09;是一种常见的网络攻击方式&#xff0c;通过向SQL查询中插入恶意的SQL代码&#xff0c;攻击者可以操控数据库&#xff0c;SQL注入是一种代码注入攻击&#xff0c;其中攻击者将恶意的SQL代码插入到应用程序的输入字段中&am…...

OpenAI 重回巅峰:ChatGPT-4O 最新模型超越谷歌 Gemini 1.5,多项测试夺冠!

谷歌上周发布的Gemini 1.5 Pro模型&#xff0c;在LMSYS办的聊天机器人竞技场Chatbot Arena中获得第一名。但是&#xff0c;OpenAI迅速反应&#xff0c;推出了最新的chatgpt-4o-latest模型&#xff0c;重新夺回了冠军头衔。 chatgpt-4o-latest模型简介 OpenAI最近推出了名为gpt-…...

软件工程(2)面向对象方法:Booch方法与开发实例

Booch方法&#xff08;Booch Method&#xff09;是由Grady Booch提出的一种面向对象的软件开发方法。它是一种系统分析与设计的框架&#xff0c;主要用于设计和建模面向对象的系统。Booch方法特别关注对象模型的构建&#xff0c;以及类、对象和它们之间的关系。以下是Booch方法…...

高阶面试-concurrentHashMap的整理

算不上死磕&#xff0c;里面太痛苦了&#xff0c;现在很多位移等操作还看不懂&#xff0c;只是先理清大致思路&#xff0c;面试用 concurrentHashMap的实现原理 为啥会用到&#xff1f;并发安全。之前都用的hashtable实现线程安全的map&#xff0c;但是太过笨重&#xff0c;不…...

VSCode系列 - 如何用VSCode搭建C++高效开发环境(1)

VSCode是笔者用过的最好用的开发工具&#xff0c;没有之一。笔者14年的码龄生涯中&#xff0c;先后用过Eclipse、 IntelliJ IDEA、 WebStorm、 PyCharm、 Visual Studio(2010/2013/2015)、 NetBeans、 Sublime Text等&#xff0c;但自从用VSCode之后&#xff0c;就再没换过其他…...

【人工智能】Python融合机器学习、深度学习和微服务的创新之路

1. &#x1f680; 引言1.1 &#x1f680; 人工智能的现状与发展趋势1.2 &#x1f4dc; 机器学习、深度学习和神经网络的基本概念1.3 &#x1f3c6; 微服务架构在人工智能中的作用 2. &#x1f50d; 机器学习的演变与创新2.1 &#x1f31f; 机器学习的历史回顾2.2 &#x1f9e0;…...

Stability AI发布了单目视频转4D模型的新AI模型:Stable Video 4D

开放生成式人工智能初创公司Stability AI在3月发布了Stable Video 3D&#xff0c;是一款可以根据图像中的物体生成出可旋转的3D模型视频工具。Stability AI在7月24日发布了新一代的Stable Video 4D&#xff0c;增添了赋予3D模移动作的功能。 Stable Video 4D能在约40秒内生成8…...

网站如何被Google收录?

想让你的网站快速被Google收录&#xff1f;试试GSI快速收录服务吧&#xff0c;这是通过谷歌爬虫池系统来实现的。这套系统吸引并圈养Google爬虫&#xff0c;提高你网站的抓取频率。每天有大量Google爬虫抓取你的网站页面&#xff0c;大大提高了页面的收录概率&#xff0c;从而增…...

LearnOpenGL——法线贴图、视差贴图学习笔记

LearnOpenGL——法线贴图、视差贴图学习笔记 法线贴图 Normal Mapping一、基本概念二、切线空间1. TBN矩阵2. 切线空间中的法线贴图 三、复杂模型四、小问题 视差贴图 Parallax Mapping一、基本概念二、实现视差贴图三、陡峭视差映射 Steep Parallax Mapping四、视差遮蔽映射 P…...

界面优化 - 绘图

目录 1. 基本概念 2. 绘制各种形状 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 2.5 设置画笔 2.6 设置画刷 3. 绘制图片 3.1 绘制简单图片 3.2 平移图片 3.3 缩放图片 3.4 旋转图片 1. 基本概念 虽然 Qt 已经内置了很多的控件, 但是不能保证现有控件就…...

死锁问题分析和解决——资源回收时

1.描述问题 在完成线程池核心功能功能时&#xff0c;没有遇到太大的问题&#xff08;Any,Result,Semfore的设计&#xff09;&#xff0c;在做线程池资源回收时&#xff0c;遇到了死锁的问题 1、在ThreadPool的资源回收&#xff0c;等待线程池所有线程退出时&#xff…...

【Java】效率工具模板的使用

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 乱码问题4.2 快捷键模板4.3 文件模板 一、前言 提高效率 二、学习内容&am…...

c++指南 -指针和引用

指针和引用 指针的基本概念 指针是存储另一个变量的内存地址的变量。指针变量的声明包括指针类型和星号 (*)。 int* ptr; // ptr 是一个指向 int 类型的指针指针操作 初始化&#xff1a;将指针设置为变量的地址。 int var 10; int* ptr &var; // ptr 现在存储 var 的…...

[CISCN 2023 华北]ez_date

[CISCN 2023 华北]ez_date 点开之后是一串php代码&#xff1a; <?php error_reporting(0); highlight_file(__FILE__); class date{public $a;public $b;public $file;public function __wakeup(){if(is_array($this->a)||is_array($this->b)){die(no array);}if( (…...

前端不同项目使用不同的node版本(Volta管理切换)

前端不同项目使用不同的node版本(Volta管理切换) 使用volta自动切换前端项目的node版本&#xff0c; 每个不同的前端项目&#xff0c;可以使用不同的node版本。Volta这个工具&#xff0c;它允许用户方便地安装、切换和管理不同版本的Node.js&#xff0c;避免了为每个项目手动配…...

Ropdump:针对二进制可执行文件的安全检测工具

关于Ropdump Ropdump是一款针对二进制可执行文件的安全检测工具&#xff0c;该工具基于纯Python开发&#xff0c;是一个命令行工具&#xff0c;旨在帮助广大研究人员检测和分析二进制可执行文件中潜在的ROP小工具、缓冲区溢出漏洞和内存泄漏等安全问题。 功能介绍 1、识别二进…...