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

发布于:2024-04-20 ⋅ 阅读:(22) ⋅ 点赞:(0)

一.交集

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切片val
	mp := make(map[string]bool)
 
	for _, value := range a {  //循环a切片
		if _, ok := mp[value ]; !ok {  //判断mp切片是否存在,不存在则设置key-value
			mp[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 []uint
	mp := 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] = 1
				inter = append(inter, s)
			}
		}
		return inter
	}
 
	// 一般情况
	// 先使用第一个切片构建map的键值对
	for _, s := range lists[0] {
		if _, ok := mp[s]; !ok {
			mp[s] = 1
		}
	}
 
	// 除去第一个和最后一个之外的list
	for _, list := range lists[1 : l-1] {
		for _, s := range list {
			if _, ok := mp[s]; ok {
				// 计数+1
				mp[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 main
 
import (
    "fmt"
    "reflect"
)
 
// 获取两个切片的交集
func Intersect(a, b []int) []int {
    m := make(map[int]bool)
 
    for _, v := range a {
        m[v] = true
    }
 
    var intersection []int
    for _, 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 []uint
	mp := 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 main
 
import (
    "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 []int
    for _, 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) 
}