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

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机