Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Go中的接口{}片上搜索接口{}的函数_Go - Fatal编程技术网

在Go中的接口{}片上搜索接口{}的函数

在Go中的接口{}片上搜索接口{}的函数,go,Go,我试图实现一个函数,它接受任何类型的元素和相同类型的片段,并在第二个元素中搜索第一个元素,给出它的位置作为结果或-1 我不是Go专家,所以我的第一个想法是将元素作为接口{}传递给搜索,并将切片作为[]接口{}传递给搜索,但它并没有真正起作用 以下是我尝试过的: 主程序包 进口( “fmt” ) func IsElementInListWithPos(元素接口{},列表[]接口{})int{ 对于i:=范围列表{ 如果列表[i]==元素{ 返回i } } 返回-1 } func main(){ 列

我试图实现一个函数,它接受任何类型的元素和相同类型的片段,并在第二个元素中搜索第一个元素,给出它的位置作为结果或-1

我不是Go专家,所以我的第一个想法是将元素作为接口{}传递给搜索,并将切片作为[]接口{}传递给搜索,但它并没有真正起作用

以下是我尝试过的:

主程序包
进口(
“fmt”
)
func IsElementInListWithPos(元素接口{},列表[]接口{})int{
对于i:=范围列表{
如果列表[i]==元素{
返回i
}
}
返回-1
}
func main(){
列表1:=[]int{1,2,3,4,5,6}
清单2:=[]字符串{“a”、“b”、“c”、“d”}
pos1:=IsElementInListWithPos(3,列表1)
pos2:=IsElementInListWithPos(“a”,列表2)
fmt.Println(位置1,位置2)
}
它给了我以下错误:

cannot use list (type []int) as type []interface {} in argument to IsElementInListWithPos
cannot use list2 (type []string) as type []interface {} in argument to IsElementInListWithPos
你知道我如何在不使用两个不同函数的情况下解决这个问题吗? 提前感谢。

演示了如何使用接口以独立于类型的方式实现算法

线性搜索需要两个基本操作,这取决于haystack元素类型Len和Equal。因此,我们可以编写以下Haystack接口和使用它的搜索函数:

类型Haystack接口{
Len()int
相等(int,接口{})bool
}
func搜索(haystack-haystack,针接口{})int{
对于i:=0;i
这使得为Haystack编写实现变得简单,但不是类型安全的:

键入字符串[]字符串
func(s字符串)Len()int{return Len(s)}
func(s Strings)Equal(i int,x interface{})bool{返回s[i]==x(string)}
输入Ints[]int
func(s Ints)Len()int{return Len(s)}
func(s int)Equal(i int,x interface{})bool{返回s[i]==x(int)}
func main(){
字符串:=[]字符串{“b”、“a”、“c”、“d”}
fmt.Println(Search(Strings,Strings),“c”)//2
fmt.Println(搜索(字符串),“e”)/-1
int:=[]int{2,1,3,4}
fmt.Println(搜索(Ints(Ints),3))//2
fmt.Println(搜索(整数,5))/-1
}
注意Equal方法中的类型断言。为了使此类型安全,我们必须去掉
接口{}
参数,使其等于:

类型Haystack接口{
Len()int
相等(整数)布尔
}
func搜索(干草堆干草堆)int{
对于i:=0;i
这使得接口实现和搜索功能的使用变得更加复杂

这个故事的寓意是,以这种方式使用接口需要一个足够复杂的算法,这样做是值得的。如果为特定类型编写接口实现比为算法编写具体实现要复杂得多,那么只需编写所需的具体函数即可:

func SearchStr(haystack[]字符串,针字符串)int{
对于i,x:=范围干草堆{
如果x==针{
返回i
}
}
返回-1
}
func SearchInt(haystack[]int,needle int)int{
对于i,x:=范围干草堆{
如果x==针{
返回i
}
}
返回-1
}
func main(){
字符串:=[]字符串{“b”、“a”、“c”、“d”}
fmt.Println(SearchStr(strings,“c”)//2
fmt.Println(SearchStr(字符串,“e”))/-1
int:=[]int{2,1,3,4}
fmt.Println(SearchInt(ints,3))//2
fmt.Println(SearchInt(ints,5))/-1
}

目前,无法构建符合所有标准的解决方案。一旦实施,这将是可能的。或者您可以尝试使用
reflect
构建一个,但这将产生一个复杂且可能缓慢的解决方案。。。因此,我通常建议不要将
reflect
用于像这样简单的事情(参见下面的第二个代码片段)

您现在可以做的是使用以下方法:

func FindFirst(n int, f func(int) bool) int {
    for i := 0; i < n; i++ {
        if f(i) {
            return i
        }
    }
    return -1
}

// in your code (s is the slice, e the value you are searching for)
i := FindFirst(len(s), func(i int) bool {
    return s[i] == e
})
if i != -1 {
    // i is the index of the element with value e
}

显然,只有当切片中的元素数量较少时,这种整体方法(线性扫描)才是合理的。如果您的切片很大并且很少更改,那么(从时间复杂性的角度来看)首先对其进行排序()然后对排序后的切片进行二进制搜索()可能更有意义。或者,您也可以使用
映射来代替:在这种情况下(假设键很小),查找将是O(1)。

不要这样做。正如你所注意到的,Go不是那样工作的。[]int和[]接口{}是完全不同的类型。这里要记住的主要事情是:
接口{}
并不意味着“任何类型”,它意味着“空接口”而不是别的。编写这样一个函数可以通过反射完成,而且非常复杂。写两个函数,甚至三个或四个。看看如何做这种事情。也就是说,编写两个简单的函数会简单得多。看看这一点可以解释为什么你们不能这么做。谢谢你们,当然在生产中,我使用了很多不同的函数,每种类型一个。我只是想知道如何把它作为一个练习来实现,这样我就可以更多地理解如何去做
// in your code (s is the slice, e the value you are searching for)
for i, v := range s {
    if v == e {
        _ = i // i is the index of the element with value e
        break
    }
}