go语言实现 in_array的问题

搬砖小师傅
  • 54

问题描述

GO语言实现in_array的问题,即判断一个值是否在slice中存在

问题出现的环境背景及自己尝试过哪些方法

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

func main()  {
    str1 := "dd"
    strArr := []string{"aa","bb","cc","dd"}   
    exists := inArray(str1, strArr)
    fmt.Println(exists)
}


func inArray(need interface{}, needArr []interface{}) bool {
     for _,v := range needArr{
        if need == v{
            return true
        }
    }
    return false
}

你期待的结果是什么?实际看到的错误信息又是什么?

期待结果是  need是可传入的任何类型的值, needArr 传入一个任何类型的slice,检查结果返回true或false,

实现错误是:
# command-line-arguments

srctestinarray.go:14:19: cannot use strArr (type []string) as type []interface {} in argument to inArray

回复
阅读 11.2k
8 个回答

这是对基础语法有误解了。
inArray 函数参数类型为 []interface{} 表示元素类型为 interface{} 的切片,是说里面每个元素都可以是不同的类型,比如 a := []interface{}{"test", 123, map[int]string{2:"bb"}} 里面的三个元素类型均不一致。
而如果传入的是指定类型像你的写 []string{}, 那么就是说切片里每一个元素都必须是 string 类型,这显然与 inArray 的形参 []interface{} 要表达的意思不符。
所以,实参类型还得是 []interface{} ,里面元素可以是任意类型的。

func main()  {
    str1 := "dd"
    strArr := []string{"aa","bb","cc","dd"}
    exists := inArray(len(strArr), func(i int) bool {return strArr[i] == str1})
    fmt.Println(exists)
}

func inArray(n int, f func(int) bool) bool {

    for i := 0; i < n; i++ {
       if f(i) {
          return true
       }
    }
    return false
}

查找这个事,只有比较函数和类型有关,算法逻辑本身和类型无关,所以把比较函数作为一个参数,就可以达到通用算法的效果了。

func maim() {
    var (
        str1   interface{}
        strArr []interface{}
    )
    str1 = "dd"
    strArr = []interface{}{"aa", "bb", "cc", "dd"}
    exists := inArray(str1, strArr)
    fmt.Println(exists)
}

func inArray(need interface{}, needArr []interface{}) bool {
    for _, v := range needArr {
        if need == v {
            return true
        }
    }
    return false
}

Go 不支持泛型的,[]xx 和 []interface{} 是两种类型。

要么写个脚本生成一堆类型的的 in_array,要么牺牲效率用 reflect。看场景。

等 Go2 吧

可以参考这个, 文中也有一些解释, 来自官方 wiki

var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
    interfaceSlice[i] = d
}

代码来源

我给你一个我写的参考的包garray,里面有排序和非排序的slice,不同类型的slice检索的方式也不一样:
https://gitee.com/johng/gf/tr...

这么简单的问题,大家竟然这么积极,果然Golang环境是越来越好了

这个必须使用反射实现.有两种实现方式

必须对interface进行断言一下. 然后才会进行对比操作

方法一

// 判断某一个值是否含在切片之中
func InArray(need interface{}, haystack interface{}) bool {
    switch key := need.(type) {
    case int:
        for _, item := range haystack.([]int) {
            if item == key {
                return true
            }
        }
    case string:
        for _, item := range haystack.([]string) {
            if item == key {
                return true
            }
        }
    case int64:
        for _, item := range haystack.([]int64) {
            if item == key {
                return true
            }
        }
    case float64:
        for _, item := range haystack.([]float64) {
            if item == key {
                return true
            }
        }
    default:
        return false
    }
    return false
}

方法二

//判断某一个值是否含在切片之中
func In_Array(val interface{}, array interface{}) (exists bool, index int) {
    exists = false
    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()) == true {
                index = i
                exists = true
                return
            }
        }
    }

    return
}

源码出处

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏