详解Golang如何比较两个slice是否相等

目录
  • 前言
  • 判断两个[]byte是否相等
  • 使用reflect判断slice是否相等
  • 手写循环遍历比较
  • 性能比较
  • 总结

前言

开发中经常会遇到需要比较两个slice包含的元素是否完全相等的情况,在golang中是不能够直接通过 == 来判断两个切片是否相等的,我们通常会通过两种方法去比较切片是否相等,这里通过几个示例来看一下这两种方法,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

判断两个[]byte是否相等

因为在bytes标准库中提供了[]byte的比较方法,所以我们不再需要重复造轮子了;示例如下:

package main
import (
	"bytes"
	"fmt"
)
func main() {
	a := []byte{1,2,3}
	b := []byte{1,2}
	c := []byte{1,2,3}
	fmt.Println(bytes.Equal(a,b))
	fmt.Println(bytes.Equal(a,c))
}

执行代码输出如下:

使用reflect判断slice是否相等

我们还可以借助reflect包的reflect.DeepEqual方法来比较两个切片是否相等。这个写法很简单:

// ReflectDeepEqual 直接使用 reflect 包的 reflect.DeepEqual 方法进行比较
func StringSliceReflectEqual(a, b []string) bool {
    return reflect.DeepEqual(a, b)
}

手写循环遍历比较

我们都知道Golang中reflect效率很低,使用reflect通常需要付出性能代价,如果我们确定了slice的类型,那么自己实现slice的相等判断相对来说也不是那么麻烦:

// LoopCompare 循环遍历比较
// 先比较两个数的长度是否相等
// 再循环遍历每一个元素进行比较
func LoopCompare(a, b []int) bool {
    if len(a) != len(b) {
        return false
    }
    //与reflect.DeepEqual的结果保持一致:[]int{} != []int(nil)
    if (a == nil) != (b == nil) {
        return false
    }
    for i, v := range a {
        if v != b[i] {
            return false
        }
    }
    return true
}

性能比较

借助Benchmark来简单的测试比较下二者的性能。

package test

import (
	"reflect"
	"testing"
)

var (
	testA = []int{1,3,5,9,11,13}
	testB = []int{1,3,5,9,11,13,17,23}
)

// BenchmarkReflectDeepEqual 测试 reflect.DeepEqual 效率
func BenchmarkReflectDeepEqual(b *testing.B) {
	for n := 0; n < b.N; n++ {
		ReflectDeepEqual(testA, testB)
	}
}

// BenchmarkLoopCompare 测试 循环比较 效率
func BenchmarkLoopCompare(b *testing.B) {
	for n := 0; n < b.N; n++ {
		LoopCompare(testA, testB)
	}
}

在测试文件所在目录执行go test -bench=.命令

Benchmark对比测试结果:

根据测试结果我们可以得到:

  • 使用reflect的方式,649 ns完成一次操作;
  • 使用循环遍历的方式,12.7 ns完成一次比较,效率对比十分明显。

原因在于reflect 接收任意类型的参数,方法内部要对类型做判断;循环遍历仅支持已知固定类型,效率自然要高些。所以就只能忍痛放弃reflect了。

总结

以上就是整理的golang 判断 两个slice 是否相等全部内容,我们可以借助reflect包的reflect.DeepEqual方法来比较两个切片是否相等,但是效率比较低,如果我们确定了slice的类型,我们可以手写遍历循环的方式来比较,相对效率比较高,希望文章能够帮你解决golang 判断 两个slice 是否相等所遇到的程序开发问题。

到此这篇关于详解Golang如何比较两个slice是否相等的文章就介绍到这了,更多相关Golang比较slice是否相等内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-11-18

Go基础系列:Go切片(分片)slice详解

slice表示切片(分片),例如对一个数组进行切片,取出数组中的一部分值.在现代编程语言中,slice(切片)几乎成为一种必备特性,它可以从一个数组(列表)中取出任意长度的子数组(列表),为操作数据结构带来非常大的便利性,如python.perl等都支持对数组的slice操作,甚至perl还支持对hash数据结构的slice. 但Go中的slice和这些语言的slice不太一样,前面所说的语言中,slice是一种切片的操作,切片后返回一个新的数据对象.而Go中的slice不仅仅是一种切片动作,还

go 判断两个 slice/struct/map 是否相等的实例

可以通过 reflect.DeepEqual 比较两个 slice/struct/map 是否相等: package main import ( "fmt" "reflect" ) type A struct { s string } func main() { a1 := A{s: "abc"} a2 := A{s: "abc"} if reflect.DeepEqual(a1, a2) { fmt.Println(a1,

Go之集合slice的实现

目录 Slice(切片) 基于数组生成切片 切片修改 切片声明 Append 切片元素循环 Slice(切片) 切片和数组类似,可以把它理解为动态数组.切片是基于数组实现的,它的底层就是一个数组.对数组任意分隔,就可以得到一个切片.现在我们通过一个例子来更好地理解它,同样还是基于前面的 array. 基于数组生成切片 下面代码中的 array[2:5] 就是获取一个切片的操作,它包含从数组 array 的索引 2 开始到索引 5 结束的元素: array:=[5]string{"a",

Go语言--切片(Slice)详解

目录 一.定义切片 1.声明一个未指定大小的数组来定义切片 2.使用make()函数来创建切片 二.切片是可索引的 1.len() 和 cap() 函数 三.切片截取 四.增加切片的容量 说明: Go 语言切片是对数组的抽象. Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大. 一.定义切片 注意:切片不需要说明长度 1.声明一个未指定大小

对Python 数组的切片操作详解

高级特性 切片操作:对list,tuple元素进行截取操作,非常简便. L[0:3],L[:3] 截取前3个元素. L[1:3] 从1开始截取2个元素出来. L[-1] 取倒数第一个元素出来. L[-10] 取后10个数 L[10:20] 取前11-20个数 L[:10:2] 取前10个数,每两个取一个 L[::5] 所有数,每5个取一个 L[:] 原样复制一个list tuple,字符串也可以进行切片操作 以上这篇对Python 数组的切片操作详解就是小编分享给大家的全部内容了,希望能给大家一

易语言子程序知识点详解

将程序分割成较小的逻辑组件就可以简化程序设计任务,这些逻辑组件被称为子程序. 子程序可用于压缩重复任务或共享任务,例如,压缩频繁的计算处理等等. 用子程序编程有两大好处: 子程序可使程序划分成离散的逻辑组件,每个组件都比无子程序的整个程序容易调试及理解: 一个应用程序中的子程序,往往不必修改或只需稍作改动,便可以成为另一个程序的子程序. 每次调用子程序时,子程序中的所有语句都将被从第一条开始顺序执行,当执行到子程序尾部或者遇到"返回"命令时即返回到调用此子程序语句的下一条语句处. 子程

Spring表达式语言SpEL用法详解

这篇文章主要介绍了spring表达式语言SpEL用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 (1)spring表达式语言是一个支持运行时查询和操作对象图得我强大表达式语言. (2)语言类似于EL:SpEL使用#{...}作为定界符.所有在大括号中的字符串均被认为是SpEL. (3)SpEL为bean的属性进行动态赋值提供了便利. (4)通过SpEL可以实现: 通过Bean的id对Bean进行引用 调用方法及引用对象的属性 计算表达式

R语言数据类型深入详解

R语言用来存储数据的对象包括: 向量, 因子, 数组, 矩阵, 数据框, 时间序列(ts)以及列表 意义介绍 1. 向量(一维数据): 只能存放同一类型的数据 语法: c(data1, data2, ...),访问的时候下标从1开始(和Matlab相同);向量里面只能存放相同类型的数据. > x <- c(1,5,8,9,1,2,5) > x [1] 1 5 8 9 1 2 5 > y <- c(1,"zhao") # 这里面有integer和字符串, 整

R语言关联规则深入详解

在用R语言做关联规则分析之前,我们先了解下关联规则的相关定义和解释. 关联规则的用途是从数据背后发现事物之间可能存在的关联或者联系,是无监督的机器学习方法,用于知识发现,而非预测. 关联规则挖掘过程主要包含两个阶段:第一阶段从资料集合中找出所有的高频项目组,第二阶段再由这些高频项目组中产生关联规则. 接下来,我们了解下关联规则的两个主要参数:支持度和置信度. 用简化的方式来理解这两个指标,支持度是两个关联物品同时出现的概率,而置信度是当一物品出现,则另一个物品也出现的概率. 假如有一条规则:牛肉

R语言“循环”知识点详解

可能有一种情况,当你需要执行一段代码几次. 通常,顺序执行语句. 首先执行函数中的第一个语句,然后执行第二个语句,依此类推. 编程语言提供允许更复杂的执行路径的各种控制结构. 循环语句允许我们多次执行一个语句或一组语句,以下是大多数编程语言中循环语句的一般形式 - R编程语言提供以下种类的循环来处理循环需求. 单击以下链接以检查其详细信息. Sr.No. 循环类型和描述 1 repeat循环 多次执行一系列语句,并简化管理循环变量的代码. 2 while循环 在给定条件为真时,重复语句或语句组.

C语言字符串数组详解

C语言字符串数组 字符串是连续的字符序列,最后以空字符'\0'作为终止符.一个字符串的长度指所有字符的数量,但不包括终止符.在 C 语言中,没有字符串类型,自然也就没有运算符以字符串为操作数. 字符串被存储在元素类型为 char 或宽字符类型数组中(宽字符类型指 wchar_t.char16_t 或 char32_t).宽字符组成的字符串也称为宽字符串(wide string). C 标准库提供了大量的函数,它们可以对字符串进行基本操作,例如字符串的比较.复制和连接等.在这些传统的字符串函数以外

C语言lseek()函数详解

 头文件: #include <sys/types.h> #include <unistd.h> 函数原型: off_t lseek(int fd, off_t offset, int whence);//打开一个文件的下一次读写的开始位置 参数: fd 表示要操作的文件描述符 offset是相对于whence(基准)的偏移量 whence 可以是SEEK_SET(文件指针开始),SEEK_CUR(文件指针当前位置) ,SEEK_END为文件指针尾 返回值: 文件读写指针距文件开头

关于C语言qsort函数详解

目录 C语言qsort函数详解 一.qsort函数是什么 二.使用qsort排序-以升序为例 1.整形数组排序 2.字符数组排序 3.字符指针数组排序 4.结构体数组排序 5.浮点型数组排序 三.使用冒泡排序思想模拟实现qsort函数 1.什么是冒泡排序 2.冒泡排序代码 3. 使用冒泡排序思想模拟实现qsort函数 C语言qsort函数详解 一.qsort函数是什么 我们可以使用  搜索库函数网址或者MSDN软件进行查找. qsort()函数:快速排序的函数  -引用stdlib.h头文件 参