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删除切片元素的另一种姿势的主要内容,如果未能解决你的问题,请参考以下文章

Go删除切片元素的另一种姿势

位运算的另一种姿势

Golang入门到项目实战 | go语言切片元素的添加和删除copy

转换为 ISO 字符串后返回日期/时间而不切片的另一种方法?

Go语言自学系列 | go语言切片元素的添加和删除copy

[C++多线程]1.3-多线程控制的另一种姿势-条件变量(condition_variable), 信号量(semaphore)