2012-11-22 138 views
15

檢查特定值是否在字符串切片中的最佳方法是什麼?我會用其他語言的Set,但Go沒有。檢查字符串切片是否包含特定值Go

我最好的嘗試是這個至今:

package main 

import "fmt" 

func main() { 
    list := []string{"a", "b", "x"} 
    fmt.Println(isValueInList("b", list)) 
    fmt.Println(isValueInList("z", list)) 
} 

func isValueInList(value string, list []string) bool { 
    for _, v := range list { 
     if v == value { 
      return true 
     } 
    } 
    return false 
} 

http://play.golang.org/p/gkwMz5j09n

這個解決方案應該是確定的小片,但如何處理許多元素片嗎?

回答

37

如果你以任意順序串片,發現某個值存在於片需要O (n)時間。這適用於所有語言。

如果您打算一遍又一遍地執行搜索,則可以使用其他數據結構更快地進行查找。但是,構建這些結構至少需要O(n)個時間。因此,如果您不止一次使用數據結構進行查找,您將只會獲益。

例如,您可以將您的字符串加載到地圖中。然後查找將花費O(1)次。插入也需要O(1)時間作出初步建成取O(n)的時間:

set := make(map[string]bool) 
for _, v := range list { 
    set[v] = true 
} 

fmt.Println(set["b"]) 

您還可以排序您的串片,然後做一個二進制搜索。二進制搜索發生在O(log(n))時間。建築物可以花費O(n * log(n))時間。

sort.Strings(list) 
i := sort.SearchStrings(list, "b") 
fmt.Println(i < len(list) && list[i] == "b") 

雖然在理論上給定的值無限多,地圖也比較快,在實踐中極有可能搜索排序列表會更快。你需要自己進行基準測試。

4

要替換集合,您可以使用map[string]whatever。這不會是你可以想象的更輕(有一個指向你不需要的值的指針),但除了編寫你自己的哈希表之外,它是最有效的,並且它是內置的非常優化的。

set := make(map[string]uint8) 

爲了把一個項目:

set[item]=1 

要檢查的項目存在:

_, ok = set[item] 

這是Go中常見的成語。如果確定是真的,那麼該項目是存在的。如果確定是錯誤的,那麼該項目不存在。

+6

對於慣用的Go,您可以使用'map [keyType] struct {}'(一個空的零大小的結構體作爲值)或'map [keyType] bool'來實現此功能,而** not ** uint8如圖所示。對於前者,您可以使用顯示的'_,ok:= set [item]'構造。如果使用bool,只要設置[item]'作爲不存在的條目返回[「零值」](https://golang.org/ref/spec#The_zero_value),這對於bool而言是假的。 –

2

您可以使用地圖,並具有例如一個布爾

m := map[string] bool {"a":true, "b":true, "x":true} 
if m["a"] { // will be false if "a" is not in the map 
    //it was in the map 
} 

另外還有sort包,所以你可以排序和二進制搜索你的片

+2

請注意,您不必使用bool虛擬值。你可以像這樣使用一個空的結構:'map [string] struct {}'。 – nemo

+3

只是爲了闡明@nemo所說的,使用struct {}作爲值的優點是它不需要內存。 –

+2

「它不需要內存」...對於這些值,當然映射仍然需要內存來存儲鍵和散列表(或其他任何實現),它只是最小化映射使用的內存(代價是「if _ ,ok:= map [「a」]; ok' style只檢查'if map [「a」]')。 –

相關問題