Learn Go (四) 數(shù)組, 切片, 字符串應(yīng)用和處理

數(shù)組

定義

var, := 關(guān)鍵字; 元素?cái)?shù)量寫在類型前面

var arr1 [5] int // 中括號(hào)數(shù)字, 是指定元素個(gè)數(shù), 默認(rèn)元素為 0
arr2 := [3] int {1, 2, 3}
arr3 := [...] int {4, 5, 6, 7, 8} // 讓編譯器計(jì)算元素個(gè)數(shù)

var grid [4][5] int // 代表 4 行 5 列  二維數(shù)組, 只能用 var 聲明

遍歷

// 方式一
arr3 := [...] int {1, 3, 5, 7, 9}

for i := 0; i < len(arr3); i++ {

    fmt.println(arr3[i])
} 

// 方式二
for i := range arr3 {
   fmt.Println(arr3[i])
}

// 方式三, 輸出 i, v 
for i, v := range arr3 {
    fmt.println(i, v)
}

// 只輸出 v, 使用 "_" 替換 i 
for _, v := range arr3 {
    fmt.println(v)
}

類型

  • 數(shù)組是值類型

    package main
    
    import "fmt"
    
    func printArray(arr [5]int)  {
    
      // 若此處將數(shù)組下標(biāo)為 0 的元素,會(huì)重新賦值成100
      arr[0] = 100
      for i, v := range arr {
         fmt.Println(i, v)
      }
    
    }
    
    
    func main() {
      var arr1 [5] int // 中括號(hào)數(shù)字, 是指定元素個(gè)數(shù), 默認(rèn)元素為 0
      arr2 := [3] int {1, 2, 3}
      arr3 := [...] int {4, 5, 6, 7, 8} // 讓編譯器計(jì)算元素個(gè)數(shù)
    
      var grid [4][5] int // 二維數(shù)組, 只能用 var 聲明
    
    
      fmt.Println(arr1, arr2, arr3) // 這里輸出的數(shù)組還是原來的數(shù)組, 沒有改變
      fmt.Println(grid)
      printArray(arr3)
    }
    

小結(jié)

  • [10] int[20] int 是不同的類型
  • 調(diào)用 func f(arr [10] int) 會(huì)重新 拷貝 一個(gè)數(shù)組
  • Go 語言中一般不直接使用數(shù)組

切片 slice

概念

Go 語言切片是對(duì)數(shù)組的抽象醇份°擦椋可以理解成數(shù)組的 view

Go 數(shù)組的長度不可改變领炫,在特定場(chǎng)景中這樣的集合就不太適用饵蒂,Go 中提供了一種靈活辛辨,功能強(qiáng)悍的內(nèi)置類型切片("動(dòng)態(tài)數(shù)組"),與數(shù)組相比切片的長度是不固定的拷邢,可以追加元素香府,在追加時(shí)可能使切片的容量增大。

操作

基操
 package main

 import "fmt"

 // slice 不是值傳遞,可以看成 視圖
 func updateSlice(s []int)  {
    s[0] = 100
 }



 func main() {

    arr := [...] int {0, 1, 2, 3, 4, 5, 6, 7}


    fmt.Println("arr[2:6] = ", arr[2:6])
    fmt.Println("arr[:6] = ", arr[:6])

    s1 := arr[2:]
    fmt.Println("s1 = ", s1)
    s2 := arr[:]
    fmt.Println("s2 = ", s2)

    fmt.Println("After updateSlice(s1)")
    updateSlice(s1)
    fmt.Println(s1)
    fmt.Println(arr)

    fmt.Println("After updateSlice(s2)")
    updateSlice(s2)
    fmt.Println(s2)
    fmt.Println(arr)
    
    
     fmt.Println("Reslice")
     fmt.Println(s2)
     s2 = s2[:5]
     fmt.Println(s2)
     s2 = s2[2:]
     fmt.Println(s2)


 }

 
     // 結(jié)果
     arr[2:6] =  [2 3 4 5]
     arr[:6] =  [0 1 2 3 4 5]
     s1 =  [2 3 4 5 6 7]
     s2 =  [0 1 2 3 4 5 6 7]
     After updateSlice(s1)
     [100 3 4 5 6 7]
     [0 1 100 3 4 5 6 7]
     After updateSlice(s2)
     [100 1 100 3 4 5 6 7]
     [100 1 100 3 4 5 6 7]
     Reslice
     [100 1 100 3 4 5 6 7]
     [100 1 100 3 4]
     [100 3 4]

擴(kuò)展

arr := [...] int {0, 1, 2, 3, 4, 5, 6, 7}

s1 := arr[2:6]

s2 := s1[3:5]

問 :

  • s1 的值?

  • s2 的值?

    s1 的值 [2 3 4 5]
    s2 的值 [5 6]
    

答 :

s1arr 中取得新數(shù)組 [2, 3, 4, 5], 那么 s1 的下標(biāo)分別是 0, 1, 2, 3; 由于s1arr 的 view, s1arr 存在映射關(guān)系. arr 中的元素 6, 7 對(duì)應(yīng)著 s1 不可見下標(biāo) 4, 5; s2 獲取 s13,5 等同于獲取 arr 中的 5, 7; 左開右閉 原則, 所以 s2 的值就是 [5, 6]

answer.png
  • 知識(shí)點(diǎn)
![image.png](https://upload-images.jianshu.io/upload_images/19614659-b84b90b9531acc90.image?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- `slice` 可以向后擴(kuò)展, 不可以向前擴(kuò)展
- `s[i]` 不可以超越 `len(s)`, 向后擴(kuò)展不可以超越底層數(shù)組 `cap(s)`
添加元素

arr := [...] int {0, 1, 2, 3, 4, 5, 6, 7}

s1 := arr[2:6]

s2 := s1[3:5]

s3 := append(s2, 10)

s4 := append(s3, 11)

s5 := append(s4, 12)

問 : s3, s4, s5 的值為多少? arr的值又變成

結(jié)果 :
[2 3 4 5]
[5 6]
[5 6 10]
[5 6 10 11]
[5 6 10 11 12]
  • 關(guān)鍵字 append
  • 添加元素時(shí)如果超越 cap, 系統(tǒng)會(huì)重新分配更大的底層數(shù)組
  • 由于值傳遞關(guān)系, 必須接收 append 的返回值
  • s = append(s, val)
復(fù)雜操作
  • 追加

    append(s, v) 第一個(gè)參數(shù)是追加的 slice, 第二個(gè)是 element

    func main () {
        var s [] int // 空的 slice, 默認(rèn) 0 填充 
        
        for i := 0; i < 100; i++ {
        
            s = append (s, 2 * i + 1)
        }
        
    }
    
    
    
  • 設(shè)置指定長度的 slice

    make([]int, 16, 32) 第一個(gè)參數(shù)創(chuàng)建類型, 第二個(gè)參數(shù)是長度, 第三個(gè)是分配的空間(可選)

    // 建立長度為 16 的 slice
    s2 := make([]int, 16)
    s3 := make([]int, 10, 32)
    
  • 復(fù)制 slice

    copy(s1, s2) 第一個(gè)參數(shù)是要復(fù)制的目標(biāo)slice恼策,第二個(gè)參數(shù)是源slice

    s1 := [] int {2, 3, 4, 5}
    s2 := make([]int, 16)
    
    copy(s2, s1)
    // 結(jié)果
    [2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0], len = 16, cap = 16
    
    
  • 刪除一個(gè)元素

    沒有刪除函數(shù), 采取截取, 再拼接的方式實(shí)現(xiàn)刪除

    s2 = append(s2[:3] , s2[4:]...)
    // 結(jié)果
    [2 3 4 0 0 0 0 0 0 0 0 0 0 0 0], len = 15, cap = 16
    
  • 頭部 Pop 一個(gè)元素

    同樣, 也是采取截取的方式

    s2 = s2[1:]
    
    // 結(jié)果
    [3 4 0 0 0 0 0 0 0 0 0 0 0 0], len = 14, cap = 15
    
  • 尾部 Pop 一個(gè)元素

    同樣, 也是采取截取的方式

    s2 = s2[:len(s2) - 1]
    
    // 結(jié)果
    [3 4 0 0 0 0 0 0 0 0 0 0 0], len = 13, cap = 15
    

Map

定義

關(guān)鍵字 map[k]v 格式 :

map[K]V, map[K1]map[K2]V

示例

創(chuàng)建
// 示例 一
m := map[string] string {
    "name" : "mouse",
    "course" : "golang",
    "site" : "imooc"
}

// 示例 二
m2 := make(map[string]int) // m2 == empty mpa

// 示例 三
var m3 map[string]int // m3 == nil 
   
應(yīng)用
  • 循環(huán)輸出

    // 循環(huán)輸出 map 
    for k, v := range m {
        fmt.println(k, v)
    }
    
    // 結(jié)果, 可以出來 map 的 k 是無序的
    site imooc
    quality good
    name mouse
    course golang
    Getting values
    
  • 獲取其中一個(gè)值

    // 獲取 map 其中一個(gè)值
    courseName, ok := m["course"]
    fmt.println(courseName, ok)
    
    // 結(jié)果
    golang true
    
  • k 不存在

    // 若獲取的 k 不存在, 則返回 空 
    causeName, ok2 := m["cause"]
    fmt.println(causeName, ok2)
    // 結(jié)果
    "" false
    // 改寫
    if causeName, ok2 := m["cause"]; ok {
        fmt.println(causeName)
    } else {
        fmt.println("key does no exist")
    }
    // 結(jié)果
    key does not exist
    
    
  • 刪除一個(gè)值 delete(), 第一個(gè)參數(shù)是 map, 第二個(gè)參數(shù)是要?jiǎng)h除的 key

    name, ok := m["name"]
    fmt.println(name, ok)
     
    delete(m, "name")
    // 結(jié)果  
    map[course:golang quality:good site:imooc]
    
小結(jié)
  • 創(chuàng)建: make(map[string]int)
  • 獲取元素 : map[key]
  • key 不存在時(shí), 則取得 Value 類型的初始值, 不會(huì)報(bào)錯(cuò)
  • 使用 value, ok := m[key] 兩個(gè)值來判斷 key 是否存在
  • 使用 delete(m, key) 刪除一個(gè)值
  • 使用 range 遍歷 key, 或者遍歷 key, value 對(duì)
  • 不能保證遍歷順序, 若需要順序, 可以添加到 slice 再對(duì) slice 排序
  • 使用 len 獲得元素個(gè)數(shù)
  • map 使用哈希表, 必須可以比較相等
  • 除了 slice, map, func 的內(nèi)建類型都可以作為 key
  • strut 類型不包含上述字段, 也可以作為 key

高級(jí)操作

例子 一

尋找最長不含有重復(fù)字符的子串

abcabcbb ---> abc

bbbbb ---> b

pwwkew ---> wke

image.png

對(duì)于每一個(gè)字母 x

  • lastOccurred[x] 不存在, 或者 < start, 無需操作

  • lastOccurred[x] >= start, 則更新 start

  • 更新 lastOccurred[x], 更新 maxLength

    func lengthOfNonRepeatingSubStr(s string) int  {
       lastOccurred := make(map[byte]int)
       start := 0
       maxLength := 0
       for i, ch := range []byte(s){
    
          lastI, ok := lastOccurred[ch]
          if ok && lastI >= start {
             start = lastI + 1
          }
          if i - start + 1 > maxLength {
             maxLength = i - start + 1
          }
          lastOccurred[ch] = i
       }
       return maxLength
    
    }
    

    計(jì)算中文等漢字會(huì)出現(xiàn)問題

字符和字符串處理

rune 相當(dāng)于 Go 的 char

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "Yes中文!"
    fmt.println(s) // 輸出結(jié)果: 10
    
    for _, b := range []byte(s) {
        fmt.printf("%X ", b)  // 輸出十六進(jìn)制
    }   
}

// 引入 unicode/utf8 包
fmt.Println("Rune count", utf8.RuneCountInString(s)) // 輸出6

bytes := []byte(s)
for len(bytes) > 0 {
    ch, size := utf8.DecodeRune(bytes)
    bytes = bytes[size:]
    
    fmt.printf("%c ", ch) // 輸出 Y e s 中 文 !
}

// 使用 rune, 可直接輸出漢字
for i, ch := range []rune(s) {
    fmt.printf("(%d, %c)", i, ch) // 輸出 (0, Y)(1, e)(2, s)(3, 中)(4, 文)(5, !)
}

再對(duì)上面的例子 一, 遺留的問題進(jìn)行修改

func lengthOfNonRepeatingSubStr(s string) int  {
   // 將 byte 修改成 rune 即可解決 
   lastOccurred := make(map[rune]int) 
   start := 0
   maxLength := 0
   // 將 byte 修改成 rune 即可解決
   for i, ch := range []rune(s){

      lastI, ok := lastOccurred[ch]
      if ok && lastI >= start {
         start = lastI + 1
      }
      if i - start + 1 > maxLength {
         maxLength = i - start + 1
      }
      lastOccurred[ch] = i
   }
   return maxLength
   
}
  • 其他字符操作

    推薦使用 strings package 來處理, 里面有很多函數(shù), 多多嘗試就會(huì)用了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸦致,一起剝皮案震驚了整個(gè)濱河市潮剪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌分唾,老刑警劉巖抗碰,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绽乔,居然都是意外死亡弧蝇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門折砸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來看疗,“玉大人,你說我怎么就攤上這事睦授×椒迹” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵去枷,是天一觀的道長怖辆。 經(jīng)常有香客問我,道長沉填,這世上最難降的妖魔是什么疗隶? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮翼闹,結(jié)果婚禮上斑鼻,老公的妹妹穿的比我還像新娘。我一直安慰自己猎荠,他們只是感情好坚弱,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著关摇,像睡著了一般荒叶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上输虱,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天些楣,我揣著相機(jī)與錄音,去河邊找鬼宪睹。 笑死愁茁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亭病。 我是一名探鬼主播鹅很,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼罪帖!你這毒婦竟也來了促煮?” 一聲冷哼從身側(cè)響起邮屁,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎菠齿,沒想到半個(gè)月后佑吝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡泞当,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年迹蛤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片襟士。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盗飒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出陋桂,到底是詐尸還是另有隱情逆趣,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布嗜历,位于F島的核電站宣渗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏梨州。R本人自食惡果不足惜痕囱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暴匠。 院中可真熱鬧鞍恢,春花似錦、人聲如沸每窖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窒典。三九已至蟆炊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瀑志,已是汗流浹背涩搓。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劈猪,地道東北人昧甘。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像岸霹,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子将饺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容