首先整理一下删除切片的常用方法
现在有一个切片slice
- slice = append(slice[:n]:slice[n+1])
- slice = slice[1:]等等
本文针对一个特殊场景:
现有切片A,B,切片B中的部分元素是切片A的子集,求A删除B中子集后的部分
先上常规思路代码:
for k, v := range A {
for _, m := range B {
if v == m {
switch k {
case 1:
A = A[1:]
case len(A):
A = A[:len(A)-1]
default:
A = append(A[:k], A[k+1:]...)
}
}
}
}
乍一看,简单粗暴,万无一失,然而当我们运行之后,一定会panic,原因是数组越界
原因很简单,切片A的实际长度一直在减少,然而在循环中的index并不会,在操作A = append(A[:k], A[k+1:]...)
一定会造成越界
这个时候如果你去百度《go删除切片元素》,那么一定会得到以下答案
A = A[1:]
A = A[:len(A)-1]
A = append(A[:k], A[k+1:]...)
本文提供一种方式,(注:仅为分享该方式,并不仅有此方式)
在go语言中,map一直是slice的好朋友,map与slice结合可是实现很多功能,例如去重等等,但是却往往却忽略了另一项list(链表)
在Go语言中container/list
提供了链表结构,链表删除节点的效率无疑是要比slice高很多的,关于该包的详细内容可自行百度,但是官方提供的包对于pop操作并不是很支持,由于本人一直在使用GoFrame框架,这里提供github.com/gogf/gf/container/glist
,也可以去GoFrame官网自行了解
废话有点多,开始操作
- 将B转换为map
C := make(map[string]int)
for _,v := range B{
C[v] = 1 //值并不重要
}
- 将只属于A的元素添加到list
list := glist.New()
for _, k := range A{
_, ok := C[k] //判断是否已经存在
if !ok {
list.PushBack(k) //不存在则加入list
}
}
- 得到需要的数据list,根据场景可以方便的对list进行操作,已经变换为想要的数据结构
list.PopFrontAll()
list.PopBackAll()
关于glist的介绍:https://goframe.org/pages/viewpage.action?pageId=7297433