小编典典

有没有一种方法可以编写通用代码来确定切片中是否包含Go中的特定元素?

go

我想知道是否存在一种通用的方法来编写代码来判断切片是否包含元素,我发现它会经常有用,因为有很多逻辑可以判断切片中是否已存在特定的elem,然后决定要处理的内容。接下来。但是似乎没有内置的方法(为了上帝,为什么?)

我尝试使用interface{}这样做:

func sliceContains(slice []interface{}, elem interface{}) bool {
    for _, item := range slice {
       if item == elem {
          return true
       }
    }
    return false
}

我以为interface{}有点像ObjectJava,但显然我错了。我每次遇到新的切片时都应该写这个吗?没有通用的方法可以做到这一点吗?


阅读 306

收藏
2020-07-02

共1个答案

小编典典

您可以使用进行此操作reflect,但它比非泛型等效函数要 得多:

func Contains(slice, elem interface{}) bool {

    sv := reflect.ValueOf(slice)

    // Check that slice is actually a slice/array. 
    // you might want to return an error here
    if sv.Kind() != reflect.Slice && sv.Kind() != reflect.Array {
        return false
    }

    // iterate the slice
    for i := 0; i < sv.Len(); i++ {

        // compare elem to the current slice element
        if elem == sv.Index(i).Interface() {
            return true
        }
    }

    // nothing found
    return false


}

func main(){
    si := []int {3, 4, 5, 10, 11}
    ss := []string {"hello", "world", "foo", "bar"}

    fmt.Println(Contains(si, 3))
    fmt.Println(Contains(si, 100))
    fmt.Println(Contains(ss, "hello"))
    fmt.Println(Contains(ss, "baz"))

}

慢多少? 大约慢x50-x60 :对以下形式的非泛型函数进行基准测试:

func ContainsNonGeneic(slice []int, elem int) bool {
    for _, i := range slice {
        if i == elem {
            return true
        }
    }
    return false
}

我越来越:

  • 通用: N=100000, running time: 73.023214ms 730.23214 ns/op
  • 非通用: N=100000, running time: 1.315262ms 13.15262 ns/op
2020-07-02