golang实现获取切片的交集和差集

2024-04-20 03:36

本文主要是介绍golang实现获取切片的交集和差集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.交集

1.两个切片的交集

采用map实现取两个切片的交集,其中如果map[key]访问成功,即有key这个键,ok为true,否则ok为false。,以string类型为例:

//a 切片, b 切片
func intersect(a []string, b []string) []string {//初始化一个切片inter := make([]uint, 0)/初始化一个map[string]bool  : string为a切片valmp := make(map[string]bool)for _, value := range a {  //循环a切片if _, ok := mp[value ]; !ok {  //判断mp切片是否存在,不存在则设置key-valuemp[value] = true}}for _, val := range b {  //循环b切片if _, ok := mp[val]; ok {  //判断mp中是否存在b切片的值,如果存在,则append切片数据到inter中inter = append(inter, val)}}return inter
}

调试:

a := []string{"1", "2", "3", "4", "5", "1", "66", "6"}
b := []string{"6", "7", "", "4", "5", "2"}
for _, s := range intersect(a, b) {println(s)
}输出:
6
4
5
2

2.多个切片的交集

方法一

主要思路和2个切片时相同,区别就是把map的value类型改为了int用于计数,最后通过计数和传进的lists的长度关系判断是否需要该元素,以uint类型的切片为例:

// intersect 获取交集
func intersect(lists ...[]uint) []uint {var inter []uintmp := make(map[uint]int)l := len(lists)// 特判 只传了0个或者1个切片的情况if l == 0 {return make([]uint, 0)}if l == 1 {for _, s := range lists[0] {if _, ok := mp[s]; !ok {mp[s] = 1inter = append(inter, s)}}return inter}// 一般情况// 先使用第一个切片构建map的键值对for _, s := range lists[0] {if _, ok := mp[s]; !ok {mp[s] = 1}}// 除去第一个和最后一个之外的listfor _, list := range lists[1 : l-1] {for _, s := range list {if _, ok := mp[s]; ok {// 计数+1mp[s]++}}}for _, s := range lists[l-1] {if _, ok := mp[s]; ok {if mp[s] == l-1 {inter = append(inter, s)}}}return inter
}

调试: 

 
a := []uint{1, 6, 5, 1, 5, 1, 69, 1, 2}
b := []uint{1, 2, 3}
c := []uint{2, 3, 4, 5, 6}
d := intersect(a, b, c)
for _, i := range d {println(i)
}输出:
2
方法二

MultipleIntersect 函数可以接受任意数量的切片作为参数,并返回它们的交集,它通过递归调用Intersect函数来实现这一点,Intersect函数用于两个切片的交集计算,这里使用了一个辅助map来优化搜索效率

package mainimport ("fmt""reflect"
)// 获取两个切片的交集
func Intersect(a, b []int) []int {m := make(map[int]bool)for _, v := range a {m[v] = true}var intersection []intfor _, v := range b {if m[v] {intersection = append(intersection, v)}}return intersection
}// 获取多个切片的交集
func MultipleIntersect(s ...[]int) []int {if len(s) == 0 {return nil}result := s[0]for i := 1; i < len(s); i++ {result = Intersect(result, s[i])}return result
}func main() {slice1 := []int{1, 2, 3, 4, 5}slice2 := []int{4, 5, 6, 7, 8}slice3 := []int{7, 8, 9, 10}intersection := MultipleIntersect(slice1, slice2, slice3)fmt.Println(intersection) // 输出交集: [8 7]
}

二.差集

1.两个切片的差集

方法一

从将第一个切片中的元素保存到map中,然后遍历第二个切片,如果该key存在,则删除该key

// minus 获取差集
func minus(a []uint, b []uint) []uint {var inter []uintmp := make(map[uint]bool)for _, s := range a {if _, ok := mp[s]; !ok {mp[s] = true}}for _, s := range b {if _, ok := mp[s]; ok {delete(mp, s)}}for key := range mp {inter = append(inter, key)}return inter
}

 调试:

a := []uint{1, 6, 5, 1, 5, 1, 69, 1, 2}
b := []uint{1, 2, 3}
d := minus(a, b)
for _, i := range d {println(i)
}输出:
6
5 
69
方法二

可以通过遍历一个切片,然后检查元素是否存在于其他切片中来获取多个切片的差集,以下是一个简单的函数,用于获取两个或多个切片的差集

package mainimport ("fmt"
)// 获取两个切片的差集
func Difference(s1, s2 []int) []int {m := make(map[int]bool)// 将s1中的元素设置为出现在map中for _, v := range s1 {m[v] = true}// 遍历s2,如果s2中的元素不在map中,则加入结果切片var diff []intfor _, v := range s2 {if !m[v] {diff = append(diff, v)}}return diff
}func main() {slice1 := []int{1, 2, 3, 4, 5}slice2 := []int{4, 5, 6, 7, 8}difference := Difference(slice1, slice2)fmt.Println("Difference:", difference) 
}

2.多个切片的差集

如果需要获取更多切片的差集,可以对上述函数进行递归或者使用Difference函数的结果作为输入来连续调用

// 获取多个切片的差集
func DifferenceMultiple(slices ...[]int) []int {result := slices[0]for _, slice := range slices[1:] {result = Difference(result, slice)}return result
}func main() {slice1 := []int{1, 2, 3, 4, 5}slice2 := []int{4, 5, 6, 7, 8}slice3 := []int{1, 2, 9, 10}difference := DifferenceMultiple(slice1, slice2, slice3)fmt.Println("Difference:", difference) 
}

这篇关于golang实现获取切片的交集和差集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/919200

相关文章

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

golang中reflect包的常用方法

《golang中reflect包的常用方法》Go反射reflect包提供类型和值方法,用于获取类型信息、访问字段、调用方法等,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值... 目录reflect包方法总结类型 (Type) 方法值 (Value) 方法reflect包方法总结

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互