65.Slice处理工具【Sort、Contains、Find】

文章目录

  • 一、排序
    • 1、sort包介绍
    • 2、对自定义结构体集合进行排序
    • 3、sort包的相关函数
    • 4、sort包已经支持的内部数据类型排序
      • 1、IntSlice 类型及[]int 排序
      • 2、Float64Slice 类型及[]float64 排序与IntSlice类似
      • 3、StringSlice 类型及[]string 排序
    • 5、自定义结构体的简单化排序
  • 二、包含Contains
  • 三、查找Find

Go语言中,Slice是非常重要且使用频率极高的数据结构,但标准库对于Slice结构提供的方法很少。因此对于常见的排序、包含、查找等,我们可以自己提前写好工具包,方便要用的时候直接取用。

一、排序

1、sort包介绍

该包内部实现了插入排序,归并排序,堆排序和快速排序,但并不对外公开,即并不需要我们通过参数传入具体使用何种排序算法,而是在使用的时候会自动选择高效的排序算法。

外部Slice结构在使用的时候需要实现sort.Interface定义的三个方法

  • Len():获取集合长度
  • Less():比较两个元素大小的
  • Swap():交换两个元素位置。

sort包对切片类型提供了完整的支持,主要包括

  • 对基本数据类型切片的排序支持
  • 基本数据元素查找
  • 判断基本数据类型切片是否已经排好序
  • 对排好序的数据集合逆序

2、对自定义结构体集合进行排序

package main
import ("fmt""sort"
)
// 学生成绩结构体
type StuScore struct {name  string    // 姓名score int   // 成绩
}
type StuScores []StuScore
//Len()获取集合长度
func (s StuScores) Len() int {return len(s)
}
//Less(): 两个集合元素进行比较,return true不执行Swap(),false执行。
// 可简单记为小于号则是从小到大排序,因为i位置的元素在前面,不和后面j位置更大的元素交换
func (s StuScores) Less(i, j int) bool {return s[i].score < s[j].score
}//Swap()对的两个元素制定移动规则
func (s StuScores) Swap(i, j int) {s[i], s[j] = s[j], s[i]
}
func main() {stus := StuScores{{"alan", 95},{"hikerell", 91},{"acmfly", 96},{"leao", 90},}// 打印未排序的 stus 数据fmt.Println("Default:\n\t",stus)//StuScores 已经实现了 sort.Interface 接口 , 所以可以调用 Sort 函数进行排序sort.Sort(stus)// 判断是否已经排好顺序,将会打印 truefmt.Println("IS Sorted?\n\t", sort.IsSorted(stus))// 打印排序后的 stus 数据fmt.Println("Sorted:\n\t",stus)
}

输出结果:

Default:[{alan 95} {hikerell 91} {acmfly 96} {leao 90}]
IS Sorted?true
Sorted:[{leao 90} {hikerell 91} {alan 95} {acmfly 96}]

3、sort包的相关函数

  1. sort.Reverse():可以允许将数据按 Less() 定义的排序方式逆序排序,而不必修改 Less() 代码。

例如sort.Sort(sort.Reverse(stus))实现逆序。

//内部实现
// 定义了一个 reverse 结构类型,嵌入 Interface 接口
type reverse struct {Interface
}//内部的Less()与自定义的Less()有着相反的逻辑
func (r reverse) Less(i, j int) bool {return r.Interface.Less(j, i)
}// 返回新的实现 Interface 接口的数据类型
func Reverse(data Interface) Interface {return &reverse{data}
}
// 把stus传入到Recerse()方法中,返回在reverse结构体中的Interface,
// 然会外部调用Less的时候实际上是调用reverse结构体实现的Less方法,这个Less()方法与外部的有着相反的逻辑
sort.Sort(sort.Reverse(stus))//
fmt.Println(stus)
  1. sort.Search():
//方法定义
func Search(n int, f func(int) bool) int
// 该方法会使用“二分查找”算法来找出能使 f(x)(0<=x<n) 返回 ture 的最小值 i,即返回切片[0:n]索引对应元素第一个符合f函数的元素。 
// 前提条件 ,切片已经是有序的: 即f(x)(0<=x<i) 均返回 false, f(x)(i<=x<n) 均返回 ture。 如果不存在 i ,则返回 n。
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)
}

4、sort包已经支持的内部数据类型排序

1、IntSlice 类型及[]int 排序

内部实现
由于[]int 切片排序内部实现及使用方法与[]float64 []string 类似,所以只详细描述该部分。

//IntSlice 类型及[]int 排序
//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)) }

func Ints(a []int) { Sort(IntSlice(a)) }:默认升序排序

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]

func SearchInts(a []int, x int) int :查找切片中元素,需要提前进行升序排序

2、Float64Slice 类型及[]float64 排序与IntSlice类似

go内部实现

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

3、StringSlice 类型及[]string 排序

内部实现

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

5、自定义结构体的简单化排序

sort.Slice():不稳定排序

    people := []struct {Name stringAge  int
}{{"Gopher", 7},{"Alice", 55},{"Vera", 24},{"Bob", 75},
}sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age }) // 按年龄升序排序
fmt.Println("Sort by age:", people)

sort.SliceStable():稳定排序,原集合中相同数据排序后仍然保持原集合的顺序

   people := []struct {Name stringAge  int
}{{"Gopher", 7},{"Alice", 55},{"Vera", 24},{"Bob", 75},
}sort.SliceStable(people, func(i, j int) bool { return people[i].Age > people[j].Age }) // 按年龄降序排序
fmt.Println("Sort by age:", people)

sort.SliceIsSorted():该函数根据自定义的规则判断集合是否为有序.

   people := []struct {Name stringAge  int
}{{"Gopher", 7},{"Alice", 55},{"Vera", 24},{"Bob", 75},
}sort.Slice(people, func(i, j int) bool { return people[i].Age > people[j].Age }) // 按年龄降序排序
fmt.Println("Sort by age:", people)
fmt.Println("Sorted:",sort.SliceIsSorted(people,func(i, j int) bool { return people[i].Age < people[j].Age }))

sort.Search():该函数判断集合是否存在指定元素,举个栗子:

a := []int{2, 3, 4, 200, 100, 21, 234, 56}
x := 21sort.Slice(a, func(i, j int) bool { return a[i] < a[j] })   // 升序排序
index := sort.Search(len(a), func(i int) bool { return a[i] >= x }) // 查找元素if index < len(a) && a[index] == x {fmt.Printf("found %d at index %d in %v\n", x, index, a)
} else {fmt.Printf("%d not found in %v,index:%d\n", x, a, index)
}

二、包含Contains

我们这里就写几个常见类型的,其他的类似

func ContainsString(s []string, v string) bool {for _, vv := range s {if vv == v {return true}}return false
}func ContainsInt(s []int, v int) bool {for _, vv := range s {if vv == v {return true}}return false
}func ContainsInt64(s []int64, v int64) bool {for _, vv := range s {if vv == v {return true}}return false
}func ContainsFloat64(s []float64, v float64) bool {for _, vv := range s {if vv == v {return true}}return false
}

需要注意的是ContainsFloat64函数,对于浮点数的比较很多情况下我们不会用==号,而是对比两个浮点数相减是都小于某个很小的数

三、查找Find

对于查找,我们不是说列表中有某个指定的元素,那是上面介绍的包含,这里的查找指的是包含符合某条件的元素。既然要看列表中的元素是否符合某个元素,所以需要传递一个函数作为参数。

同样,也只给出常用类型的。

返回第一个符合条件的元素和索引。用-1表示列表中没有符合给定条件的元素。

func FindString(s []string, f func(v string) bool) (string, int) {for index, value := range s {result := f(value)if result {return value, index}}return "", -1
}func FindInt(s []int, f func(v int) bool) (int, int) {for index, value := range s {result := f(value)if result {return value, index}}return 0, -1
}func FindInt64(s []int64, f func(v int64) bool) (int64, int) {for index, value := range s {result := f(value)if result {return value, index}}return 0, -1
}func FindFloat64(s []float64, f func(v float64) bool) (float64, int) {for index, value := range s {result := f(value)if result {return value, index}}return 0.0, -1
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/604618.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蟹目标检测数据集VOC格式400张

蟹&#xff0c;一种独特的海洋生物&#xff0c;以其强壮的身体和独特的生活习性而闻名。 蟹的身体宽厚&#xff0c;有一对锐利的大钳子&#xff0c;这使得它们在寻找食物和保护自己时非常有力。蟹的外观颜色多样&#xff0c;有绿色、蓝色、棕色和红色等&#xff0c;这使得它们在…

【软件测试】黑盒测试

《等价类划分法》 有效等价类无效等价类 &#xff08;输入条件&#xff09;10 < x < 100&#xff08;有效等价类&#xff09;10 < x < 100&#xff08;无效等价类&#xff09;x < 10 和 x >100 《边界值分析法》 基本原则 如果输入条件规定了取值范围&…

SpringIOC之support模块DelegatingMessageSource

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

React Three Fiber动画

使用静态对象和形状构建 3D 场景非常酷,但是当你可以使用动画使场景栩栩如生时,它会更酷。 在 3D 世界中,有一个称为角色装配的过程,它允许你创建称为骨架的特殊对象,其作用类似于骨骼和关节系统。 这些骨架连接到一块 3D 几何体上,例如人、动物或其他任何物体,并允许你…

UFW 要点:常见防火墙规则和命令

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 UFW 要点&#xff1a;常见防火墙规则和命令 介绍 UFW&#xff08;uncomplicated fire wall&#xff09;是一个…

Java学习——设计模式——结构型模式2

文章目录 结构型模式装饰者模式桥接模式外观模式组合模式享元模式 结构型模式 结构型模式主要涉及如何组合各种对象以便获得更好、更灵活的结构。虽然面向对象的继承机制提供了最基本的子类扩展父类的功能&#xff0c;但结构型模式不仅仅简单地使用继承&#xff0c;而更多地通过…

ssm基于BS的项目监管系统+jsp论文

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

NX/UG二次开发—C\C++开发单个DLL支持多版本NX一种方法

1、去除附加包含目录下的NX相关的lib文件&#xff1a; 2、从对应的dll导出ufun函数和NXopen函数&#xff1a; libufun.dll; libufun_cam.dll; libufun_cae.dll; libufun_die.dll; libufun_vdac.dll; libufun_weld.dll; libugopenint.dll; libugopenint_cae.dll; libugopenint_…

Apache HTTPD 换行解析漏洞(CVE-2017-15715)详解

Apache HTTPD 换行解析漏洞&#xff08;CVE-2017-15715&#xff09; 1.cd到CVE-2017-15715 cd vulhub/httpd/CVE-2017-15715 2.运行docker-compose build docker-compose build 3.运行docker-compose up -d 4.查看docker-compose ps 5.访问 出现这个表示安装成功 6.漏洞复现…

C练习——鸡兔同笼

题目&#xff1a; 有若干只鸡和兔子在同一个笼子里&#xff0c;从上面数&#xff0c;有98个头&#xff1b;从下面数&#xff0c;有386只脚。问笼中各有几只鸡和兔&#xff1f; 解析&#xff1a; 数学上列二元一次方程组求解&#xff0c;所以采用穷举法&#xff0c;但可以缩小…

[SpringBoot]接口的多实现:选择性注入SpringBoot接口的实现类

最近在项目中遇到两种情况&#xff0c;准备写个博客记录一下。 情况说明&#xff1a;Service层一个接口是否可以存在多个具体实现&#xff0c;此时应该如何调用Service&#xff08;的具体实现&#xff09;&#xff1f; 其实之前的项目中也遇到过这种情况&#xff0c;只不过我采…

rax3000m 刷机 uboot + immortalwrt

0. 环境 - win10 ubuntu22 - rax3000m 生产日期20231027 一台&#xff08;nand版本的&#xff09; 1. 上电&#xff0c;登录web 电脑连接路由器LAN1 http://192.168.10.1/ 账号&#xff1a;user 密码&#xff1a;KK6kYC!3 上网设置&#xff1a;自动获取IP 2. 开启 ssh 2…

有趣的前端知识(一)

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 文章目录 推荐阅读HTML简介基础声明HTML标签标题段落注释水平线文本格式化标签超链接图像<i…

Vue2 - 数据响应式原理

目录 1&#xff0c;总览2&#xff0c;Observer3&#xff0c;Dep4&#xff0c;Watcher5&#xff0c;Schedule 1&#xff0c;总览 vue2官网参考 简单介绍下上图流程&#xff1a;以 Data 为中心来说&#xff0c; Vue 会将传递给 Vue 实例的 data 选项&#xff08;普通 js 对象&a…

吴飞教授 人工智能 模型与算法 启发式搜索课件发散分析

一、文章介绍 本文是针对吴飞教授在MOOC课程 &#xff1a;《人工智能&#xff1a;模型与算法》 2.1节 启发式搜索的课前发散 在课程2.1节 启发式搜索章节中&#xff0c;吴飞教授以如何计算城市地图两点之间最短路径为例&#xff0c;重点讲授了贪婪最佳优先搜索和A*搜索算法&a…

Cadence Editor 关于画PCB相关内容

目录 一 新建PCB文件 二 指定封装库 三 导入网表 四 放置器件 五 绘制板框 六 精准定位 七 原理图与PCB的交互 八 飞线设置 九 层管理 布局布线阶段需要显示的层 十 器件位置相关 1 器件选取的基准点 2 旋转 3 对齐 4 把器件移动到底层或顶层 5 锁定与解锁 6…

媒体捕捉-iOS自定义二维码扫描功能

引言 随着iOS 7引入AV Foundation框架&#xff0c;二维码扫描功能已经成为iOS应用程序中不可或缺的一部分。现今&#xff0c;几乎每个应用都充分利用这一功能&#xff0c;为用户提供了诸如扫码登录、扫码填充等丰富多彩的便捷体验。这项技术不仅丰富了应用功能&#xff0c;也为…

20240106 SQL基础50题打卡

20240106 SQL基础50题打卡 1164. 指定日期的产品价格 产品数据表: Products ------------------------ | Column Name | Type | ------------------------ | product_id | int | | new_price | int | | change_date | date | ---------------------…

20240104----重返学习-关于`npm --legacy-peer-deps`与`npm --force`升级版本

记–legacy-peer-deps与–force的了解与思考 之前还是旧的版本: "bpmn-js": "^7.3.1","bpmn-js-properties-panel": "^0.37.2","houtaroy-bpmn-js-properties-panel-activiti": "^0.0.1",使用npm install bpmn-js…

力扣(leetcode)第392题判断子序列(Python)

392.判断子序列 题目链接&#xff1a;392.判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;…