我想检查值是否在一片值中。实现这一目标的最佳方法是什么? 如下所示:
if "foo" in []string{"foo", "bar"}...
我已经编写了以下代码,但不确定它是如何惯用的(golang newbie):
// Convert a slice or array of a specific type to array of interface{}
func ToIntf(s interface{}) []interface{} {
v := reflect.ValueOf(s)
// There is no need to check, we want to panic if it's not slice or array
intf := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
intf[i] = v.Index(i).Interface()
}
return intf
}
func In(s []interface{}, val interface{}) bool {
for _, v := range s {
if v == val {
return true
}
}
return false
}
所以,使用它,这是我写的测试方法。
func TestIn(t *testing.T) {
s := []string{"foo", "bar", "kuku", "kiki"}
for _, v := range s {
if !In(ToIntf(s), v) {
t.Error("Should be in")
}
}
if In(ToIntf(s), "foobar") {
t.Error("Should not be in")
}
}
答案 0 :(得分:8)
用于通过简单循环表示的函数的惯用方法,以这种方式实现。例如,您的方法可以这样编写:
for _, value := range slice {
if value == var {
doSomething()
}
}
显然,它有点冗长,但只有当你尝试翻译 language or choice here
时才会这样。
进行反思的缺点是,如果你编写代码以集成到搜索中而不是简单地将其视为一个条件,那么就会使性能变得非常简单。
答案 1 :(得分:0)
如果你需要一种便宜的方法来检查这个(如果你必须经常检查),我会使用地图进行更便宜的查找。像这样:
type Foo string
var sl []string
var m map[string]int
//insert
sl = append(sl, "bar")
m["bar"] += 1
// delete ,e.g at position i
m[sl[i]] -= 1
sl[len(sl)-1], s[:len(sl)-1]
//test
if count := m["abc"]; count>0 {
// "abc" in sl
}
当然,如果您更改切片中的内容,两者都会增加开销。这取决于你的情况。
如果你的切片没有改变,你会做很多&#34; in&#34;测试你可以为它建立一个更容易的地图:
m := make(map[string]struct{}, len(sl))
for _, value := range sl {
m[value] = struct{}
}
//test
if _, ok := m["abc"]; ok {
// "abc" is in sl
}