Go删除切片元素的另一种姿势
Posted StaticAuto
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go删除切片元素的另一种姿势相关的知识,希望对你有一定的参考价值。
首先整理一下删除切片的常用方法
现在有一个切片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
以上是关于Go删除切片元素的另一种姿势的主要内容,如果未能解决你的问题,请参考以下文章
Golang入门到项目实战 | go语言切片元素的添加和删除copy
转换为 ISO 字符串后返回日期/时间而不切片的另一种方法?
[C++多线程]1.3-多线程控制的另一种姿势-条件变量(condition_variable), 信号量(semaphore)