Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于比较两个字符串切片的疑惑 #2

Open
OhYee opened this issue Feb 16, 2021 · 0 comments
Open

关于比较两个字符串切片的疑惑 #2

OhYee opened this issue Feb 16, 2021 · 0 comments

Comments

@OhYee
Copy link

OhYee commented Feb 16, 2021

@geektutu

关于该部分内容

## Q13 如何判断 2 个字符串切片(slice) 是相等的?
<details>
<summary>答案</summary>
<div>
go 语言中可以使用反射 `reflect.DeepEqual(a, b)` 判断 a、b 两个切片是否相等,但是通常不推荐这么做,使用反射非常影响性能。
通常采用的方式如下,遍历比较切片中的每一个元素(注意处理越界的情况)。
```go
func StringSliceEqualBCE(a, b []string) bool {
if len(a) != len(b) {
return false
}
if (a == nil) != (b == nil) {
return false
}
b = b[:len(a)]
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
```
</div>
</details>

这里我试了一下,貌似 reflect.DeepEqual 的效率实际上是比 for 循环要高的

package main

import (
	"math/rand"
	"reflect"
	"testing"
	"time"
)

var (
	l  = 100000
	l2 = 100
	s1 = generate(l)
	s2 = generate(l)
	s3 = generate(l * 2)
)

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

func randStringRunes(n int) string {
	rand.Seed(time.Now().UnixNano())
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func generate(n int) []string {
	s := make([]string, n)
	for i := 0; i < n; i++ {
		s[i] = randStringRunes(l2)
	}
	return s
}

func cmp1(a, b []string) bool {
	return reflect.DeepEqual(a, b)
}

func cmp2(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	if (a == nil) != (b == nil) {
		return false
	}
	b = b[:len(a)]
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}

func BenchmarkReflect(b *testing.B) {
	for i := 0; i < b.N; i++ {
		cmp1(s1, s2)
		cmp1(s1, s3)
		cmp1(s1, s1)
	}
}

func BenchmarkFor(b *testing.B) {
	for i := 0; i < b.N; i++ {
		cmp2(s1, s2)
		cmp2(s1, s3)
		cmp2(s1, s1)
	}
}

l = 100000l2=100时,

$ go test -bench=.
goos: linux
goarch: amd64
BenchmarkReflect-4       1235326               856 ns/op
BenchmarkFor-4              2890            354342 ns/op
PASS

l = 100l2=100000时,

$  go test -bench=.
goos: linux
goarch: amd64
BenchmarkReflect-4       1205154               866 ns/op
BenchmarkFor-4           3315399               373 ns/op
PASS

好像只有切片长度很短时,for 循环具有优势,但是优势也并不大

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant