有没有一种惯用的方式来为 golang 切片做“in”

我想检查一个值是否在一个值中。实现这一目标的最佳方法是什么?类似于以下内容:


if "foo" in []string{"foo", "bar"}...

我已经编写了以下代码,但不确定它是多么地道(golang 新手):


// 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")

    }

}


撒科打诨
浏览 276回答 2
2回答

白衣非少年

在 go 中,对于可以用简单循环表示的函数,以这种方式实现的惯用方式。例如,您的方法可以这样编写:for _, value := range slice {&nbsp; &nbsp; if value == var {&nbsp; &nbsp; &nbsp; &nbsp; doSomething()&nbsp; &nbsp; }}显然,它有点冗长,但前提是您尝试在 go 中进行翻译 language or choice here。进行反射的缺点是,您会破坏性能,而不会比编写代码以集成到搜索中而不是简单地将其视为一个条件那么简单。

三国纷争

如果您需要一种便宜的方法来检查这个(如果您必须经常检查),我会使用地图进行更便宜的查找。像这样:type Foo stringvar sl []stringvar m map[string]int//insertsl = append(sl, "bar")m["bar"] += 1// delete ,e.g at position im[sl[i]] -= 1sl[len(sl)-1], s[:len(sl)-1]//testif count := m["abc"]; count>0 {&nbsp;// "abc" in sl&nbsp;}当然,如果您更改切片中的某些内容,两者都会增加开销。那要看你的情况了。如果您的切片没有改变,并且您将进行大量“in”测试,您可以为此构建一个更简单的地图:m := make(map[string]struct{}, len(sl))for _, value := range sl {&nbsp; &nbsp; m[value] = struct{}}//test&nbsp;if _, ok := m["abc"]; ok {&nbsp; // "abc" is in sl}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go