有没有办法编写通用代码来确定切片是否包含Go中的特定元素? [英] Is there a way to write generic code to find out whether a slice contains specific element in Go?

查看:181
本文介绍了有没有办法编写通用代码来确定切片是否包含Go中的特定元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有一种通用的方法来编写代码来判断一个切片是否包含一个元素,我发现它通常很有用,因为有很多逻辑来判断特定元素是否已经在一个切片中,然后决定下一步该做什么。但似乎没有内置的方法(为了上帝的缘故,为什么?)



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

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

我以为 interface {} 像Java的 Object ,但显然,我错了。我应该每次都遇到一个新的slice结构时写这个吗?是不是有一种通用的方式来做到这一点?

解决方案

您可以使用 reflect ,但它会比非泛型等价函数

  func包含(slice,elem接口{})bool {

sv:= reflect.ValueOf(slice)

//检查切片实际上是切片/数组。
//如果sv.Kind()!= reflect.Slice&& amp;& amp;& sv.Kind()!= reflect.Array {
return false
}

//迭代切片
for i:= 0;我< sv.Len(); i ++ {

//比较elem与当前分片元素
if elem == sv.Index(i).Interface(){
return true
}
}

//找不到
返回false



$ b 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(包含(ss,baz))

}

慢多少? 约x50-x60慢
针对非通用函数的形式进行基准比较:

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

p>


  • 通用: N = 100000,运行时间:73.023214ms 730.23214 ns / op li>
  • 非泛型: N = 100000,运行时间:1.315262ms 13.15262 ns / op


I want to know is there a generic way to write code to judge whether a slice contains an element, I find it will frequently useful since there is a lot of logic to fist judge whether specific elem is already in a slice and then decide what to do next. But there seemed not a built-in method for that(For God's sake, why?)

I try to use interface{} to do that like:

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

I thought interface{} is sort of like Object of Java, but apparently, I was wrong. Should I write this every time meet with a new struct of slice? Isn't there a generic way to do this?

解决方案

You can do it with reflect, but it will be MUCH SLOWER than a non-generic equivalent function:

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

}

How much slower? about x50-x60 slower: Benchmarking against a non generic function of the form:

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

I'm getting:

  • Generic: N=100000, running time: 73.023214ms 730.23214 ns/op
  • Non Generic: N=100000, running time: 1.315262ms 13.15262 ns/op

这篇关于有没有办法编写通用代码来确定切片是否包含Go中的特定元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆