2 回答

TA貢獻1871條經驗 獲得超8個贊
它的字節索引在7和4,請參閱注釋,請嘗試一下:
s1 := "ééé hannah"
s2 := "eee hannah"
s3 := "han"
fmt.Println([]rune(s3))
// [104 97 110]
fmt.Println([]rune(s1))
// [233 233 233 32 104 97 110 110 97 104]
fmt.Println([]byte(s1))
// [195 169 195 169 195 169 32 104 97 110 110 97 104]
fmt.Println(strings.Index(s1, s3))
fmt.Println([]rune(s2))
// [101 101 101 32 104 97 110 110 97 104]
fmt.Println([]byte(s2))
// [101 101 101 32 104 97 110 110 97 104]
fmt.Println(strings.Index(s2, s3))
請參閱:,它使用:Go/src/strings/strings.goIndexByte
// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
func IndexByte(s string, c byte) int {
return bytealg.IndexByteString(s, c)
}

TA貢獻1827條經驗 獲得超8個贊
因此,as wasmup 在他們的答案中已經說過:返回字節索引。您期望的是 Unicode 索引。Unicode字符實際上是多字節編碼的東西,這就是為什么輸入字符串中的3似乎被計數兩次(產生索引7而不是預期的4)。strings.Indexéé
一些背景
golang中的字符串基本上是一段字節。這就是返回它所執行的值的原因:以字節為單位找到匹配項的偏移量。但是,Unicode 處理碼位以允許使用多字節字符。golang 沒有一個相當抽象的名稱類型,而是將這種類型稱為 a 。關于這個問題還有很多話要說,但你可以在這里閱讀更多。strings.Indexcodepointrune
但是,考慮到這一點,我們可以創建自己的函數,為您提供rune索引,而不是字節索引。我們調用函數 。此類函數的現成實現可能如下所示:IndexRuneIndex
func RuneIndex(str, sub string) int {
// ensure valid input
if len(str) == 0 || len(sub) == 0 {
return -1
}
// convert to rune slices
rin, rmatch := []rune(str), []rune(sub)
// iterate over input until end of string - length of match we're trying to find
for i := 0; i < len(rin) - len(rmatch); i++ {
// slight optimisation: if the first runes don't match, don't bother comparing full substrings
if rin[i] != rmatch[0] {
continue
}
// compare substrings directly, if they match, we're done
if string(rin[i:i+len(rmatch)]) == sub {
return i
}
}
return -1
}
它基本上只是將子字符串與我們嘗試搜索的字符串的子切片進行比較。通過將符文子片轉換為字符串,我們可以只使用運算符,如果找到匹配項,則返回 ,即符文索引(而不是字節索引)。我添加了一些檢查來確保參數不為空,如果未找到索引,該函數將返回-1,類似于標準庫函數。==i
實現非常簡單,并且沒有高度優化,但是考慮到我認為這是一個想要做的利基事情,因此優化這種類型的功能無論如何都會歸類為微優化。
- 2 回答
- 0 關注
- 152 瀏覽
添加回答
舉報