亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Go 中通過一個接口{}切片搜索接口{}的函數

在 Go 中通過一個接口{}切片搜索接口{}的函數

Go
Cats萌萌 2023-07-26 13:43:11
我正在嘗試實現一個函數,該函數接受任何類型的元素和相同類型的切片,并在第二個元素中搜索第一個元素,將其位置作為結果,否則為 -1。我不是Go專家,所以我的第一個想法是將要搜索的元素作為interface{}傳遞,將切片作為[]interface{}傳遞,但它并沒有真正起作用。這是我嘗試過的:package mainimport (    "fmt")func IsElementInListWithPos(element interface{}, list []interface{}) int {    for i := range list {        if list[i] == element {            return i        }    }    return -1}func main() {    list1 := []int{1, 2, 3, 4, 5, 6}    list2 := []string{"a", "b", "c", "d"}    pos1 := IsElementInListWithPos(3, list1)    pos2 := IsElementInListWithPos("a", list2)    fmt.Println(pos1, pos2)}它給了我以下錯誤:cannot use list (type []int) as type []interface {} in argument to IsElementInListWithPoscannot use list2 (type []string) as type []interface {} in argument to IsElementInListWithPos知道如何在不實際使用兩個不同函數的情況下解決這個問題嗎?提前致謝。
查看完整描述

2 回答

?
森欄

TA貢獻1810條經驗 獲得超5個贊

sort包演示了如何使用接口以與類型無關的方式實現算法。


線性搜索需要兩個基本操作,具體取決于 haystack 元素類型:Len 和 Equal。因此,我們可以編寫以下 Haystack 接口和使用它的搜索函數:


type Haystack interface {

    Len() int

    Equal(int, interface{}) bool

}


func Search(haystack Haystack, needle interface{}) int {

    for i := 0; i < haystack.Len(); i++ {

        if haystack.Equal(i, needle) {

            return i

        }

    }

    return -1

}


這使得 Haystack 的編寫實現變得簡單,但不是類型安全的:


type Strings []string


func (s Strings) Len() int                        { return len(s) }

func (s Strings) Equal(i int, x interface{}) bool { return s[i] == x.(string) }


type Ints []int


func (s Ints) Len() int                        { return len(s) }

func (s Ints) Equal(i int, x interface{}) bool { return s[i] == x.(int) }


func main() {

    strings := []string{"b", "a", "c", "d"}

    fmt.Println(Search(Strings(strings), "c")) // 2

    fmt.Println(Search(Strings(strings), "e")) // -1


    ints := []int{2, 1, 3, 4}

    fmt.Println(Search(Ints(ints), 3)) // 2

    fmt.Println(Search(Ints(ints), 5)) // -1

}


請注意 Equal 方法中的類型斷言。為了使這個類型安全,我們必須去掉interface{}Equal 的參數:


type Haystack interface {

    Len() int

    Equal(int) bool

}


func Search(haystack Haystack) int {

    for i := 0; i < haystack.Len(); i++ {

        if haystack.Equal(i) {

            return i

        }

    }

    return -1

}


type Strings struct {

    hs     []string

    needle string

}


func (s Strings) Len() int         { return len(s.hs) }

func (s Strings) Equal(i int) bool { return s.hs[i] == s.needle }


type Ints struct {

    hs     []int

    needle int

}


func (s Ints) Len() int         { return len(s.hs) }

func (s Ints) Equal(i int) bool { return s.hs[i] == s.needle }


func main() {

    strings := []string{"b", "a", "c", "d"}

    fmt.Println(Search(Strings{strings, "c"})) // 2

    fmt.Println(Search(Strings{strings, "e"})) // -1


    ints := []int{2, 1, 3, 4}

    fmt.Println(Search(Ints{ints, 3})) // 2

    fmt.Println(Search(Ints{ints, 5})) // -1

}

這使得界面實現和搜索功能的使用變得更加復雜。


這個故事的寓意是,以這種方式使用接口需要足夠復雜的算法才值得這樣做。如果為特定類型編寫接口實現比為算法編寫具體實現需要更多工作,那么只需編寫您需要的具體函數即可:


func SearchStr(haystack []string, needle string) int {

    for i, x := range haystack {

        if x == needle {

            return i

        }

    }

    return -1

}


func SearchInt(haystack []int, needle int) int {

    for i, x := range haystack {

        if x == needle {

            return i

        }

    }

    return -1

}


func main() {

    strings := []string{"b", "a", "c", "d"}

    fmt.Println(SearchStr(strings, "c")) // 2

    fmt.Println(SearchStr(strings, "e")) // -1


    ints := []int{2, 1, 3, 4}

    fmt.Println(SearchInt(ints, 3)) // 2

    fmt.Println(SearchInt(ints, 5)) // -1

}


查看完整回答
反對 回復 2023-07-26
?
守候你守候我

TA貢獻1802條經驗 獲得超10個贊

目前,不可能構建一個符合您所有標準的解決方案。一旦實現泛型,這將成為可能。或者您可以嘗試使用 構建一個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

}

正如你可以想象的那樣,這沒有多大意義......因為簡單地顯式地寫出循環可以說更簡單、更快、更慣用:


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

    }

}

顯然,只有當切片中的元素數量很少時,整個方法(線性掃描)才合理。sort.Slice如果您的切片很大并且很少更改,那么(從時間復雜度的角度來看)首先對其進行排序 ( ),然后sort.Search對排序后的切片進行二分搜索 ( )可能更有意義?;蛘?,您也可以使用 amap來代替: 在這種情況下(假設鍵很?。┎檎业臅r間復雜度為 O(1)。


查看完整回答
反對 回復 2023-07-26
  • 2 回答
  • 0 關注
  • 169 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號