<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 7.6 字符串、數組和切片的應用 - [7.6.1 從字符串生成字節切片](#761__1) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#762-獲取字符串的某一部分)7.6.2 獲取字符串的某一部分](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md762762__2) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#763-字符串和切片的內存結構)7.6.3 字符串和切片的內存結構](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md763763__3) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#764-修改字符串中的某個字符)7.6.4 修改字符串中的某個字符](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md764764__4) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#765-字節數組對比函數)7.6.5 字節數組對比函數](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md765765__5) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#766-搜索及排序切片和數組)7.6.6 搜索及排序切片和數組](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md766766__6) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#767-append-函數常見操作)7.6.7 append 函數常見操作](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md767append767_append__7) - [\[\](https://github.com/Unknwon/the-way-to-go\_ZH\_CN/blob/master/eBook/07.6.md#768-切片和垃圾回收)7.6.8 切片和垃圾回收](#httpsgithubcomUnknwonthewaytogo_ZH_CNblobmastereBook076md768768__8) ## 7.6.1 從字符串生成字節切片 假設 s 是一個字符串(本質上是一個字節數組),那么就可以直接通過 `c := []bytes(s)` 來獲取一個字節的切片 c。另外,您還可以通過 copy 函數來達到相同的目的:`copy(dst []byte, src string)`。 同樣的,還可以使用 for-range 來獲得每個元素(Listing 7.13—for\_string.go): ``` package main import "fmt" func main() { s := "\u00ff\u754c" for i, c := range s { fmt.Printf("%d:%c ", i, c) } } ``` 輸出: ``` 0:y? 2:界 ``` 我們知道,Unicode 字符會占用 2 個字節,有些甚至需要 3 個或者 4 個字節來進行表示。如果發現錯誤的 UTF8 字符,則該字符會被設置為 U+FFFD 并且索引向前移動一個字節。和字符串轉換一樣,您同樣可以使用 `c := []int(s)` 語法,這樣切片中的每個 int 都會包含對應的 Unicode 代碼,因為字符串中的每次字符都會對應一個整數。類似的,您也可以將字符串轉換為元素類型為 rune 的切片:`r := []rune(s)`。 可以通過代碼 `len([]int(s))` 來獲得字符串中字符的數量,但使用 `utf8.RuneCountInString(s)` 效率會更高一點。(參考[count\_characters.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/exercises/chapter_4/count_characters.go)) 您還可以將一個字符串追加到某一個字符數組的尾部: ``` var b []byte var s string b = append(b, s...) ``` ## 7.6.2 獲取字符串的某一部分 使用 `substr := str[start:end]` 可以從字符串 str 獲取到從索引 start 開始到 `end-1` 位置的子字符串。同樣的,`str[start:]` 則表示獲取從 start 開始到 `len(str)-1` 位置的子字符串。而 `str[:end]` 表示獲取從 0 開始到 `end-1`的子字符串。 ## 7.6.3 字符串和切片的內存結構 在內存中,一個字符串實際上是一個雙字結構,即一個指向實際數據的指針和記錄字符串長度的整數(見圖 7.4)。因為指針對用戶來說是完全不可見,因此我們可以依舊把字符串看做是一個值類型,也就是一個字符數組。 字符串 `string s = "hello"` 和子字符串 `t = s[2:3]` 在內存中的結構可以用下圖表示: [![](https://box.kancloud.cn/2015-10-22_56288784b2451.png)](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/images/7.6_fig7.4.png) ## 7.6.4 修改字符串中的某個字符 Go 語言中的字符串是不可變的,也就是說 `str[index]` 這樣的表達式是不可以被放在等號左側的。如果嘗試運行 `str[i] = 'D'` 會得到錯誤:`cannot assign to str[i]`。 因此,您必須先將字符串轉換成字節數組,然后再通過修改數組中的元素值來達到修改字符串的目的,最后將字節數組轉換回字符串格式。 例如,將字符串 "hello" 轉換為 "cello": ``` s := "hello" c := []byte(s) c[0] = ’c’ s2 := string(c) // s2 == "cello" ``` 所以,您可以通過操作切片來完成對字符串的操作。 ## 7.6.5 字節數組對比函數 下面的 `Compare` 函數會返回兩個字節數組字典順序的整數對比結果,即 `0 if a == b, -1 if a < b, 1 if a > b`。 ``` func Compare(a, b[]byte) int { for i:=0; i < len(a) && i < len(b); i++ { switch { case a[i] > b[i]: return 1 case a[i] < b[i]: return -1 } } // 數組的長度可能不同 switch { case len(a) < len(b): return -1 case len(a) > len(b): return 1 } return 0 // 數組相等 } ``` ## 7.6.6 搜索及排序切片和數組 標準庫提供了 `sort` 包來實現常見的搜索和排序操作。您可以使用 `sort` 包中的函數 `func Ints(a []int)` 來實現對 int 類型的切片排序。例如 `sort.Ints(arri)`,其中變量 arri 就是需要被升序排序的數組或切片。為了檢查某個數組是否已經被排序,可以通過函數 `IntsAreSorted(a []int) bool` 來檢查,如果返回 true 則表示已經被排序。 類似的,可以使用函數 `func Float64s(a []float64)` 來排序 float64 的元素,或使用函數 `func Strings(a []string)`排序字符串元素。 想要在數組或切片中搜索一個元素,該數組或切片必須先被排序(因為標準庫的搜索算法使用的是二分法)。然后,您就可以使用函數 `func SearchInts(a []int, n int) int` 進行搜索,并返回對應結果的索引值。 當然,還可以搜索 float64 和字符串: ``` func SearchFloat64s(a []float64, x float64) int func SearchStrings(a []string, x string) int ``` 您可以通過查看 [官方文檔](http://golang.org/pkg/sort/) 來獲取更詳細的信息。 這就是如何使用 `sort` 包的方法,我們會在第 11.6 節對它的細節進行深入,并實現一個屬于我們自己的版本。 ## 7.6.7 append 函數常見操作 我們在第 7.5 節提到的 append 非常有用,它能夠用于各種方面的操作: 1. 將切片 b 的元素追加到切片 a 之后:`a = append(a, b...)` 2. 復制切片 a 的元素到新的切片 b 上: ``` b = make([]T, len(a)) copy(b, a) ``` 3. 刪除位于索引 i 的元素:`a = append(a[:i], a[i+1:]...)` 4. 切除切片 a 中從索引 i 至 j 位置的元素:`a = append(a[:i], a[j:]...)` 5. 為切片 a 擴展 j 個元素長度:`a = append(a, make([]T, j)...)` 6. 在索引 i 的位置插入元素 x:`a = append(a[:i], append([]T{x}, a[i:]...)...)` 7. 在索引 i 的位置插入長度為 j 的新切片:`a = append(a[:i], append(make([]T, j), a[i:]...)...)` 8. 在索引 i 的位置插入切片 b 的所有元素:`a = append(a[:i], append(b, a[i:]...)...)` 9. 取出位于切片 a 最末尾的元素 x:`x, a = a[len(a)-1], a[:len(a)-1]` 10. 將元素 x 追加到切片 a:`a = append(a, x)` 因此,您可以使用切片和 append 操作來表示任意可變長度的序列。 從數學的角度來看,切片相當于向量,如果需要的話可以定義一個向量作為切片的別名來進行操作。 如果您需要更加完整的方案,可以學習一下 Eleanor McHugh 編寫的幾個包:[slices](http://github.com/feyeleanor/slices)、[chain](http://github.com/feyeleanor/chain) 和 [lists](http://github.com/feyeleanor/lists)。 ## 7.6.8 切片和垃圾回收 切片的底層指向一個數組,該數組的實際體積可能要大于切片所定義的體積。只有在沒有任何切片指向的時候,底層的數組內層才會被釋放,這種特性有時會導致程序占用多余的內存。 **示例** 函數 `FindDigits` 將一個文件加載到內存,然后搜索其中所有的數字并返回一個切片。 ``` var digitRegexp = regexp.MustCompile("[0-9]+") func FindDigits(filename string) []byte { b, _ := ioutil.ReadFile(filename) return digitRegexp.Find(b) } ``` 這段代碼可以順利運行,但返回的 `[]byte` 指向的底層是整個文件的數據。只要該返回的切片不被釋放,垃圾回收器就不能釋放整個文件所占用的內存。換句話說,一點點有用的數據卻占用了整個文件的內存。 想要避免這個問題,可以通過拷貝我們需要的部分到一個新的切片中: ``` func FindDigits(filename string) []byte { b, _ := ioutil.ReadFile(filename) b = digitRegexp.Find(b) c := make([]byte, len(b)) copy(c, b) return c } ``` **練習 7.12** 編寫一個函數,要求其接受兩個參數,原始字符串 str 和分割索引 i,然后返回兩個分割后的字符串。 **練習 7.13** 假設有字符串 str,那么 `str[len(str)/2:] + str[:len(str)/2]` 的結果是什么? **練習 7.14** 編寫一個程序,要求能夠反轉字符串,即將 “Google” 轉換成 “elgooG”(提示:使用 `[]byte` 類型的切片)。 如果您使用兩個切片來實現反轉,請再嘗試使用一個切片(提示:使用交換法)。 如果您想要反轉 Unicode 編碼的字符串,請使用 `[]int` 類型的切片。 **練習 7.15** 編寫一個程序,要求能夠遍歷一個數組的字符,并將當前字符和前一個字符不相同的字符拷貝至另一個數組。 **練習 7.16** 編寫一個程序,使用冒泡排序的方法排序一個包含整數的切片(算法的定義可參考 [維基百科](http://en.wikipedia.org/wiki/Bubble_sort))。 **練習 7.17** 在函數式編程語言中,一個 map-function 是指能夠接受一個函數原型和一個列表,并使用列表中的值依次執行函數原型,公式為:`map ( F(), (e1,e2, . . . ,en) ) = ( F(e1), F(e2), ... F(en) )`。 編寫一個函數 `mapFunc` 要求接受以下 2 個參數: - 一個將整數乘以 10 的函數 - 一個整數列表 最后返回保存運行結果的整數列表。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看