当前位置:网站首页>Several methods for deleting specified elements in Golang slices
Several methods for deleting specified elements in Golang slices
2022-07-31 21:12:00 【m0_67401228】
文章目录
Go 并没有提供删除切片元素专用的语法或函数,需要使用切片本身的特性来删除元素.
删除切片指定元素一般有如下几种方法,本文以 []int 为例给出具体实现.
1.截取法(修改原切片)
这里利用对 slice 的截取删除指定元素.注意删除时,后面的元素会前移,所以下标 i 应该左移一位.
// DeleteSlice1 删除指定元素.
func DeleteSlice1(a []int, elem int) []int {
for i := 0; i < len(a); i++ {
if a[i] == elem {
a = append(a[:i], a[i+1:]...)
i--
}
}
return a
}
2.拷贝法(不改原切片)
这种方法最容易理解,重新使用一个 slice,将要删除的元素过滤掉.缺点是需要开辟另一个 slice 的空间,优点是容易理解,而且不会修改原 slice.
// DeleteSlice2 删除指定元素.
func DeleteSlice2(a []int, elem int) []int {
tmp := make([]int, 0, len(a))
for _, v := range a {
if v != elem {
tmp = append(tmp, v)
}
}
return tmp
}
3.移位法(修改原切片)
3.1 方式一
利用一个下标 index,记录下一个有效元素应该在的位置.遍历所有元素,当遇到有效元素,将其移动到 index 且 index 加一.最终 index 的位置就是所有有效元素的下一个位置,最后做一个截取就行了.这种方法会修改原来的 slice.
该方法可以看成对第一种方法截取法的改进,因为每次指需移动一个元素,性能更加.
// DeleteSlice3 删除指定元素.
func DeleteSlice3(a []int, elem int) []int {
j := 0
for _, v := range a {
if v != elem {
a[j] = v
j++
}
}
return a[:j]
}
3.2 方式二
创建了一个 slice,但是共用原始 slice 的底层数组.这样也不需要额外分配内存空间,直接在原 slice 上进行修改.
// DeleteSlice4 删除指定元素.
func DeleteSlice4(a []int, elem int) []int {
tgt := a[:0]
for _, v := range a {
if v != elem {
tgt = append(tgt, v)
}
}
return tgt
}
4.性能对比
假设我们的切片有 0 和 1,我们要删除所有的 0.
这里分别对长度为 10、100、1000 的切片进行测试,来上下上面四种实现的性能差异.
生成切片函数如下:
func getSlice(n int) []int {
a := make([]int, 0, n)
for i := 0; i < n; i++ {
if i%2 == 0 {
a = append(a, 0)
continue
}
a = append(a, 1)
}
return a
}
基准测试代码如下:
func BenchmarkDeleteSlice1(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = DeleteSlice1(getSlice(10), 0)
}
}
func BenchmarkDeleteSlice2(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = DeleteSlice2(getSlice(10), 0)
}
}
func BenchmarkDeleteSlice3(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = DeleteSlice3(getSlice(10), 0)
}
}
func BenchmarkDeleteSlice4(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = DeleteSlice4(getSlice(10), 0)
}
}
测试结果如下:
原切片长度为 10:
go test -bench=. main/slice
goos: windows
goarch: amd64
pkg: main/slice
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkDeleteSlice1-8 17466486 65.07 ns/op
BenchmarkDeleteSlice2-8 14897282 85.22 ns/op
BenchmarkDeleteSlice3-8 21952129 50.78 ns/op
BenchmarkDeleteSlice4-8 22176390 54.68 ns/op
PASS
ok main/slice 5.427s
原切片长度为 100:
BenchmarkDeleteSlice1-8 1652146 762.1 ns/op
BenchmarkDeleteSlice2-8 2124237 578.4 ns/op
BenchmarkDeleteSlice3-8 3161318 359.9 ns/op
BenchmarkDeleteSlice4-8 2714158 423.7 ns/op
原切片长度为 1000:
BenchmarkDeleteSlice1-8 56067 21915 ns/op
BenchmarkDeleteSlice2-8 258662 5007 ns/op
BenchmarkDeleteSlice3-8 432049 2724 ns/op
BenchmarkDeleteSlice4-8 325194 3615 ns/op
5.小结
从基准测试结果来看,性能最佳的方法是移位法,其中又属第一种实现方式较佳.性能最差的也是最常用的方法是截取法.随着切片长度的增加,上面四种删除方式的性能差异会愈加明显.
实际使用时,我们可以根据不用场景来选择.如不能修改原切片使用拷贝法,可以修改原切片使用移位法中的第一种实现方式.
参考文献
golang删除slice中特定条件的元素,优化版
【Golang】slice删除元素的性能对比
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在.深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小.自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前.因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担.添加下方名片,即可获取全套学习资料哦
边栏推荐
- 给定一个ip地址,子网掩码怎么算网络号(如何获取ip地址和子网掩码)
- 【公开课预告】:超分辨率技术在视频画质增强领域的研究与应用
- 基于STM32 环形队列来实现串口接收数据
- Socket Review and I/0 Model
- 架构实战营模块 8 作业
- linux查看redis版本命令(linux查看mysql版本号)
- find prime numbers up to n
- Book of the Month (202207): The Definitive Guide to Swift Programming
- 高通cDSP简单编程例子(实现查询高通cDSP使用率、签名),RK3588 npu使用率查询
- Teach you how to deploy Nestjs projects
猜你喜欢

Architect 04 - Application Service Encryption Design and Practice

老牌音乐播放器 WinAmp 发布 5.9 RC1 版:迁移到 VS 2019 完全重建,兼容 Win11

财务盈利、偿债能力指标

顺序表的实现

使用 Flutter 和 Firebase 制作!计数器应用程序

GAC Honda Safety Experience Camp: "Danger" is the best teacher

Redis综述篇:与面试官彻夜长谈Redis缓存、持久化、淘汰机制、哨兵、集群底层原理!...

Flink_CDC construction and simple use

Shell script quick start to actual combat -02

关注!海泰方圆加入《个人信息保护自律公约》
随机推荐
Transfer Learning - Domain Adaptation
多线程之锁
Douyin fetches video list based on keywords API
npm 更改为淘宝镜像的方法[通俗易懂]
关注!海泰方圆加入《个人信息保护自律公约》
Thymeleaf是什么?该如何使用。
顺序表的实现
OSPFv3的基本配置
给定一个ip地址,子网掩码怎么算网络号(如何获取ip地址和子网掩码)
leetcode 665. Non-decreasing Array
BM5 merge k sorted linked lists
Commonly used security penetration testing tools (penetration testing tools)
高通cDSP简单编程例子(实现查询高通cDSP使用率、签名),RK3588 npu使用率查询
Bika LIMS open source LIMS set - use of SENAITE (detection process)
Poker Game in C# -- Introduction and Code Implementation of Blackjack Rules
linux view redis version command (linux view mysql version number)
One thing to say, is outsourcing company worth it?
Linux environment redis cluster to build "recommended collection"
【AcWing】第 62 场周赛 【2022.07.30】
Daily practice——Randomly generate an integer between 1-100 and see how many times you can guess.Requirements: The number of guesses cannot exceed 7 times, and after each guess, it will prompt "bigger"