在 Golang 裏頭對字串陣列檢查特定字串是否有存在,並回傳 index
比較 reflect, wgo package, 以及 slices
結論是,code要簡潔且效能快,用 slices
// contains.go
package main
import (
"reflect"
"github.com/wxnacy/wgo/arrays"
"slices"
)
func Contains(array interface{}, val interface{}) (index int) {
index = -1
switch reflect.TypeOf(array).Kind() {
case reflect.Slice:
{
s := reflect.ValueOf(array)
for i := 0; i < s.Len(); i++ {
if reflect.DeepEqual(val, s.Index(i).Interface()) {
index = i
return
}
}
}
}
return
}
func StringsContains(array []string, val string) (index int) {
index = -1
for i := 0; i < len(array); i++ {
if array[i] == val {
index = i
return
}
}
return
}
func SliceContains(array []string, val string) (index int) {
i := slices.Index(array, val) // Use .Index() here, because other .Contains() methods return index, not boolean
return i
}
func WgoContains(array []string, val string) (index int) {
i := arrays.Contains(array, val)
return i
}
func WgoSwitchContains(array interface{}, val interface{}) (index int) {
var i int
switch val.(type) {
case string:
var arrtmp []string
s := reflect.ValueOf(array)
for i := 0; i < s.Len(); i++ {
arrtmp = append(arrtmp, s.Index(i).Interface().(string))
}
i = arrays.StringsContains(arrtmp, val.(string))
}
return i
}
func WgoStringsContains(array []string, val string) (index int) {
i := arrays.StringsContains(array, val)
return i
}
順便用 unit test 來做測試
package main
import (
"testing"
)
var sa []string = []string{"q", "w", "e", "r", "t", "a", "b", "c", "d", "f", "g", "h", "i", "j", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7"}
var needle string = "5"
func BenchmarkContains(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
Contains(sa, needle)
}
}
func BenchmarkStringsContains(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
StringsContains(sa, needle)
}
}
func BenchmarkWgoContains(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
WgoContains(sa, needle)
}
}
func BenchmarkWgoStringsContains(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
WgoStringsContains(sa, needle)
}
}
func BenchmarkWgSwitchContains(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
WgoSwitchContains(sa, needle)
}
}
func BenchmarkSliceContains(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
SliceContains(sa, needle)
}
}
結果
> go test -bench .
goos: windows
goarch: amd64
pkg: mytest
cpu: 13th Gen Intel(R) Core(TM) i7-1370P
BenchmarkContains-20 1420240 777.4 ns/op
BenchmarkStringsContains-20 25506679 55.94 ns/op
BenchmarkWgoContains-20 1000000 1059 ns/op
BenchmarkWgoStringsContains-20 21460915 48.68 ns/op
BenchmarkWgSwitchContains-20 1205704 918.1 ns/op
BenchmarkSliceContains-20 18048748 62.82 ns/op
PASS