在 Golang 中如何快速判斷字符串是否在一個數(shù)組中
在使用 Python 的時候,如果要判斷一個字符串是否在另一個包含字符串的列表中,可以使用in 關(guān)鍵詞,例如:
- name_list = ['pm', 'kingname', '青南']
- if 'kingname' in name_list:
- print('kingname 在列表里面')
但是,Golang 是沒有in這個關(guān)鍵詞的,所以如果要判斷一個字符串數(shù)組中是否包含一個特定的字符串,就需要一個一個對比:
- package main
- import "fmt"
- func in(target string, str_array []string) bool {
- for _, element := range str_array{
- if target == element{
- return true
- }
- }
- return false
- }
- func main(){
- name_list := []string{"pm", "kingname", "青南"}
- target1 := "kingname"
- target2 := "產(chǎn)品經(jīng)理"
- result := in(target1, name_list)
- fmt.Println("kingname 是否在 name_list 中:", result)
- result = in(target2, name_list)
- fmt.Println("產(chǎn)品經(jīng)理是否在 name_list 中:", result)
- }
運行效果如下圖所示:
但這種方式有一個弊端,就是要遍歷整個字符串數(shù)組。如果數(shù)組里面有100萬條數(shù)據(jù),那么平均要遍歷50萬次才能找到。這是一個非常費時間的操作。
有沒有什么辦法可以優(yōu)化這個操作呢?
如果是有序的整型數(shù)組,那么我們可以使用二分查找,把時間復(fù)雜度O(n)降到對數(shù)時間復(fù)雜度。字符串能不能也這樣操作呢?實際上是可以的。
在 Golang 中,有一個排序模塊sort,它里面有一個sort.Strings()函數(shù),可以對字符串數(shù)組進行排序。同時,還有一個sort.SearchStrings()[1]函數(shù),會用二分法在一個有序字符串數(shù)組中尋找特定字符串的索引。
結(jié)合兩個函數(shù),我們可以實現(xiàn)一個更高效的算法:
- package main
- import (
- "fmt"
- "sort"
- )
- func in(target string, str_array []string) bool {
- sort.Strings(str_array)
- index := sort.SearchStrings(str_array, target)
- if index < len(str_array) && str_array[index] == target {
- return true
- }
- return false
- }
- func main(){
- name_list := []string{"pm", "kingname", "青南"}
- target1 := "kingname"
- target2 := "產(chǎn)品經(jīng)理"
- result := in(target1, name_list)
- fmt.Println("kingname 是否在 name_list 中:", result)
- result = in(target2, name_list)
- fmt.Println("產(chǎn)品經(jīng)理是否在 name_list 中:", result)
- }
運行效果如下圖所示:
其中,sort.Strings是一個 in-place 的修改方式,是直接修改的 str_array。修改以后str_array變成有序的字符串數(shù)組。接下來通過二分查找快速定位。如果找到了,那么返回目標字符串在排序后的列表中第一次出現(xiàn)的索引。如果沒有找到,那么返回數(shù)組中最后一個元素的索引。所以只要 index 小于最后一個元素的索引,那么目標字符串肯定存在;如果等于最后一個元素的索引,但是值不等于最后一個元素,那么目標字符串就不存在于字符串數(shù)組中。
通過先排序再查詢的方式,對于100萬個元素的字符串數(shù)組,只需要查詢20次左右就能確認字符串是否存在。速度大大提升。
最后考大家一個思考題。name_list一開始是亂序的字符串數(shù)組,在上圖第23行,如果打印一下 name_list,打印出來的是經(jīng)過排序的,還是沒有經(jīng)過排序的字符串數(shù)字?