目录

在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了。

slice相等的定义

我们选择最常见的需求,也就是当两个slice的类型和长度相同,且相等下标的值也是相等的,比如:

a := []int{1, 2, 3}

b := []int{1, 2, 3}

c := []int{1, 2}

d := []int{1, 3, 2}

上述代码中a和b是相等的,c因为长度和a不同所以不相等,d因为元素的排列顺序和a不同所以也不相等。

判断两个[]byte是否相等

为什么要单独将[]byte列举出来呢?

因为标准库提供了优化的比较方案,不再需要我们造轮子了:

package main

import (

"bytes"

"fmt"

)

func main() {

a := []byte{0, 1, 3, 2}

b := []byte{0, 1, 3, 2}

c := []byte{1, 1, 3, 2}

fmt.Println(bytes.Equal(a, b))

fmt.Println(bytes.Equal(a, c))

}

运行结果如下:

使用reflect判断slice是否相等

在判断类型不是[]byte的slice时,我们还可以借助reflect.DeepEqual,它用于深度比较两个对象包括它们内部包含的元素是否都相等:

func DeepEqual(x, y interface{}) bool

DeepEqual reports whether x and y are “deeply equal,” defined as follows. Two values of identical type are deeply equal if one of the following cases applies. Values of distinct types are never deeply equal.

...

Slice values are deeply equal when all of the following are true: they are both nil or both non-nil, they have the same length, and either they point to the same initial entry of the same underlying array (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal. Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil)) are not deeply equal.

这段话的意思不难理解,和我们在本文最开始时讨论的如何确定slice相等的原则是一样的,只不过它借助了一点运行时的“黑魔法”。

看例子:

package main

import (

"fmt"

"reflect"

)

func main() {

a := []int{1, 2, 3, 4}

b := []int{1, 3, 2, 4}

c := []int{1, 2, 3, 4}

fmt.Println(reflect.DeepEqual(a, b))

fmt.Println(reflect.DeepEqual(a, c))

}

手写判断

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

func testEq(a, b []int) bool {

// If one is nil, the other must also be nil.

if (a == nil) != (b == nil) {

return false;

}

if len(a) != len(b) {

return false

}

for i := range a {

if a[i] != b[i] {

return false

}

}

return true

}

测试代码:

package main

import "fmt"

func main() {

a := []int{1, 2, 3, 4}

b := []int{1, 3, 2, 4}

c := []int{1, 2, 3, 4}

fmt.Println(testEq(a, b))

fmt.Println(testEq(a, c))

}

运行结果:

下面我们对后两种方案做个简单的性能测试,我们测试两个不相等但很相似的拥有20个元素的slice,这是在日常开发中较常见的情景:

func BenchmarkTestEq(b *testing.B) {

a := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

c := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21}

b.ResetTimer()

for i := 0; i < b.N; i++ {

_ = testEq(a, c)

}

}

func BenchmarkDeepEqual(b *testing.B) {

a := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

c := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21}

b.ResetTimer()

for i := 0; i < b.N; i++ {

_ = reflect.DeepEqual(a, c)

}

}

当然这个测试只能反应出有限的信息,正常情况下应该给出更全面的测试用例。不过在我们的演示中反射仍然付出了惊人的性能代价:

如果我们把slice的长度设为1000,那么差距就会更加明显:

func genDiffSlice(size int) ([]uint32, []uint32) {

a := make([]uint32, 0, size)

rand.Seed(time.Now().UnixNano())

for i := 0; i < size; i++ {

a = append(a, rand.Uint32())

}

b := make([]uint32, len(a))

copy(b, a)

b[len(b)-1] = rand.Uint32()

return a, b

}

func BenchmarkTestEq2(b *testing.B) {

a, c := genDiffSlice(1000)

b.ResetTimer()

for i := 0; i < b.N; i++ {

_ = testEq(a, c)

}

}

func BenchmarkDeepEqual2(b *testing.B) {

a, c := genDiffSlice(1000)

b.ResetTimer()

for i := 0; i < b.N; i++ {

_ = reflect.DeepEqual(a, c)

}

}

自己手写判断的性能更好,但是有个显而易见的弊端,当我们有多种类型的slice时我们就不得不编写不同版本的testEq,而它们唯一的不同仅仅只有slice的类型。

不过等到go2的泛型可以使用的时候,这样的弊端也就不复存在了,现在我们需要的是在代码的复杂度和运行性能上做出权衡。

标签:slice,int,fmt,golang,相等,func,byte

来源: https://blog.csdn.net/whatday/article/details/109846306

go 判断元素是否在slice_golang 判断 两个slice 是否相等相关推荐

  1. golang 判断 两个slice 是否相等

    目录 slice相等的定义 判断两个[]byte是否相等 使用reflect判断slice是否相等 手写判断 在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是sl ...

  2. selenium3 + python - expected_conditions判断元素

    expected_conditions 类 title_is: 判断当前页面的title是否完全等于(==)预期字符串,返回布尔值 title_contains : 判断当前页面的title是否包含预 ...

  3. Go 判断元素是否在切片中

    文章目录 1.问题 2.遍历查询 3.map 查询 4.性能对比 5.转换通用化 6.借助开源库 golang-set 7.小结 参考文献 1.问题 如何判断元素是否在切片中,Golang 并没有提供 ...

  4. 布隆过滤器:一种低空间成本的判断元素是否存在的方式

    简介 布隆过滤器(BloomFilter)是一种用于判断元素是否存在的方式,它的空间成本非常小,速度也很快. 但是由于它是基于概率的,因此它存在一定的误判率,它的Contains()操作如果返回tru ...

  5. android camera viewport rect,如何判断元素是否在可视区域ViewPort

    个性签名: 生如夏花,逝如冬雪:人生如此,何悔何怨. 前言: 经常需要计算元素的大小或者所在页面的位置,offsetWidth,clientWidth,scrollWidth,scrollTop这几个 ...

  6. html判断是否有滚动条,JS 判断元素是否可以滚动

    今天在解决 ios 移动端滚动穿透的问题时遇到一个问题,就是判断元素能否滚动,把这个过程记录下来.以下以纵向滚动为例,横向滚动同理. 嫌麻烦的可以直接查看代码. 基础概念 Element.scroll ...

  7. js小白操作:判断空值、判断数组最大最小值、判断map是否为空、字符串转int、取float型小数点后两位数、判断数组中是否包含某个对象

    js小白操作:判断空值.判断数组最大最小值.判断map为空的情况.字符串转int Js基础操作 一.判断空值 undefined 和 null 二.判断map是否为空 三.取数组最大最小值 1.使用 ...

  8. 7. awk数组,定义数组,判断元素是否存在,非数字下标,删除元素,查询数组

    文章目录 前言 定义数组 元素是否存在 非数字下标 删除元素 查询数组 前言 本小节会详细介绍awk当中的数组 定义数组 在awk中可以直接为数组中的元素赋值即可,示例.awk中数组的下标默认是从1开 ...

  9. python 判断元素是否在set_python之Set操作(下)

    文章目录 python之Set操作(下)5. Set删除1) 删除一个指定元素2) 随机删除一个元素3) 清空Set4) 删除整个Set 6. Set判断1) 判断两个Set是否相等2) 判断两个Se ...

最新文章

  1. 某医院DFT SCSI 300GB *8 RAID5数据恢复成功
  2. ceph对象存储折腾记
  3. leetcode 之Remove Nth Node From End of List(19)
  4. vi is failed with error E382: Cannot write, 'buftype' option is set in Linux
  5. java创建目录时带权限_java – 无法在外部存储中创建目录,尽管权限显然设置正确...
  6. 需求分析师的基本功:逻辑思维、逻辑分析与逻辑表达
  7. 最大子矩阵(信息学奥赛一本通-T1224)
  8. mycat核心配置详解(schema.xml配置)
  9. Android深度探索-卷1第二章心得体会
  10. mysql显示nan_Python将dataframe连接到MySQL时出现NaN[mysqlconnector]
  11. Linux:为什么那么多人讨厌systemd?
  12. css checkbox自动换行,CSS checkbox
  13. 各计算机系统用传输介质互连,计算机网络技术与应用.doc
  14. Python Pycharm创建虚拟环境
  15. matlab设置图片背景透明_Matlab中得到透明背景图片的方法
  16. docker容器怎么设置开机启动
  17. golang反射的类型Type与种类Kind使用
  18. 谷歌大脑组合模型霸榜 SuperGLUE,什么模型这么高?
  19. Rabbitmq使用优先级队列实现消息插队
  20. 制作一个简单HTML抗疫逆行者网页作业(HTML+CSS)

热门文章

  1. **python基础类和对象(十二)
  2. c语言程序结果 856400,《C语言程序设计教程》习题参考解析1.doc
  3. 各类型土地利用图例_给排水系统各部件及图纸你还有多少不了解?
  4. c语音学习-输入一个小写字母,输出其对应的大写字母
  5. 【专栏精选】实战:使用LeanCloud上传玩家分数,实现排行榜
  6. java list 元素去重_小猿圈Java开发之list按照元素某个字段去重详解
  7. OpenShift 4 - 为Gogs构建一个Operator
  8. OpenShift 4 - 了解Secret
  9. Newbe.McrMirror 1.1.6 发布,助您全速下载 mssql docker 镜像
  10. php71+yum源+epel,搭建CentOS在线yum源镜像服务器