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

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下