• 07-数组和切片


    数组

    数组是同一类型元素的集合。例如,整数集合 5,8,9,79,76 形成一个数组。Go 语言中不允许混合不同类型的元素,例如包含字符串和整数的数组。(译者注:当然,如果是 interface{} 类型数组,可以包含任意类型)

    注意:数组在定义阶段,长度和类型就固定了,以后不能更改

    数组的声明

    一个数组的表示形式为[n]T。n表示数组中元素的数量,T代表每个元素的类型。元素n也是该类型的一部分

    例子:最简单的定义

    package main
    import "fmt"
    
    func main() {
        var a[5]int  #定义一个长度为5的int类型数组,因为没有赋值int是0
        fmt.Println(a)
    }
    #结果
    [0 0 0 0 0]

    定义并赋初值

    package main
    import "fmt"
    
    func main() {
      #三种定义赋值的方式,因为只赋值了4个值,所以最后一个为0 var a[
    5]int=[5]int{1,2,3,4} #第一种 var a=[5]int{1,2,3,4} #第二种 a:=[5]int{1,2,3,4} #第三种 a[2]=100 #索引值为2的数据修改为100 fmt.Println(a) }
    #结果都是
    [1 2 100 4 0]

    定义时给定某位置赋值

    例子:给第5个位置设置为99

    package main
    import "fmt"
    
    func main() {
        a:=[10]int{1,2,4:99}  #注意:go语言数组不支持负索引a[-2]这样的
        fmt.Println(a)
    }
    #结果
    [1 2 0 0 99 0 0 0 0 0]

    数组是值类型

    Go 中的数组是值类型而不是引用类型。这意味着当数组赋值给一个新的变量时,该变量会得到一个原始数组的一个副本。如果对新变量进行更改,则不会影响原始数组。(*******)

    所有的函数传参都是copy传递,在python传参不可变类型是值传参,复制值的大小,可变类型是引用传参,复制值的地址传递

    package main
    import "fmt"
    
    func main() {    
        a:=[4]int{1,2,3,4}
        test6(a)
        fmt.Println(a)
    }
    func test6(b [4]int){
        b[0]=100  #b的数据修改不会影响到a
        fmt.Println(b)
    }
    #结果

    [100 2 3 4]
    [1 2 3 4]

    数组的长度

    使用len函数,得到数组的长度

    package main
    import "fmt"
    
    func main() {
        a:=[4]int{1,2,3,4}
        fmt.Println(len(a))
    }
    #结果
    4

    数组大小是类型一部分

    var a [4]int=[4]int{1,2,}
    var b [5]int=[5]int{4,5,}

    这两个数组类型不一样的,因为考虑到长度大小不一样

    与或非(&&   ||  !)

    a:=10
    if !(a>9||a<6){
    
    }

    使用range迭代数组

    用for循环遍历数组中的元素

    package main
    import "fmt"
    
    func main() {
        var a =[4]int{1,2,}
        for i:=0;i<len(a);i++{
            fmt.Println(a[i])
        }
    }
    #结果
    1 2 0 0

    Go提供了通过使用for循环的range方法来遍历数组。range返回索引和该索引处的值

    注意:如果range有两个返回值接收:一个是索引值,一个是值。如果只有一个返回值接收:就只显示索引

    package main
    import "fmt"
    
    func main() {
        var a =[4]int{1,2,}
        for i,v:=range a {  #如果有两个值接收:一个是索引,一个是值。
            fmt.Println("------",i)
            fmt.Println(v)
        }
    }

    多维数组

    package main
    import "fmt"
    
    func main() {
        var a [7][2]int   #生成7个
        a[0][1]=100
        fmt.Println(a)
    }
    #结果
    [[0 100] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0]]

    切片

    切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用

    创建切片

    带有 T 类型元素的切片由 []T 表示

    package main
    import "fmt"
    
    func main() {
        var a=[5]int{1,2,3,4,5}
        var b[]int=a[2:4]  #只是对数组的引用
        fmt.Println(b)
    }

    另外一种创建方式:直接定义,赋值

    package main
    import "fmt"
    
    func main() {
        var b[]int  #只定义了没有赋初始值
        var a=[]int{1,2,3}  #定义切片并赋初始值
        fmt.Println(a)
        fmt.Println(b)
    }
    #结果
    [1 2 3]
    []  #切片是空值,但是是nil类型,说明切片是引用传递参数

    使用make创建一个切片

    func make([]T,len,cap)[]T 通过传递类型,长度和容量来创建切片。容量是可选参数, 默认值为切片长度。make 函数创建一个数组,并返回引用该数组的切片。

    package main
    import "fmt"
    
    func main() {    
        var a=make([]int,3)
        fmt.Println(a)
    }
    #结果
    [0 0 0]

    切片的长度(len)和容量(cap)

    package main
    import "fmt"
    
    func main() {
        var a=[5]int{1,2,3,4,5}
        var b[]int=a[2:4]
        fmt.Println(len(b))     //2
        fmt.Println(cap(b))    //3  因为容量是从截取的索引位置开始算后面有多少个,所以是3
    
        var c=make([]int,3,4)  #make定义一个切片,长度为3,容量为4
        fmt.Println(len(c))      //3
        fmt.Println(cap(c))     //4
    }

    切片的修改

    切片自己不拥有任何数据。它只是底层数组的一种表示。对切片所做的任何修改都会反映在底层数组中。

    底层数组的修改会影响切片,切片的修改也会影响底层数组

    package main
    import "fmt"
    
    func main() {
        var a=[5]int{1,2,3,4,5}
        var b[]int=a[2:4]
    
        a[2]=100
        b[1]=20
        fmt.Println(a)
        fmt.Println(b)  //本来是[3,4],但是原数组和切片都改了都会互相影响数据值
    }
    #结果
    [1 2 100 20 5]
    [100 20]

    切片追加值

    正如我们已经知道数组的长度是固定的,它的长度不能增加。 切片是动态的,使用 append 可以将新元素追加到切片上。append 函数的定义是 func append(s[]T,x ... T)[]T

    x ... T 在函数定义中表示该函数接受参数 x 的个数是可变的。这些类型的函数被称为[可变函数]。

    有一个问题可能会困扰你。如果切片由数组支持,并且数组本身的长度是固定的,那么切片如何具有动态长度。以及内部发生了什么,当新的元素被添加到切片时,超过原本的容量,会创建一个新的数组。现有数组的元素被复制到这个新数组中,并返回这个新数组的新切片引用。现在新切片的容量是旧切片的两倍。对创建新的数组进行修改,不会对原本的数组进行改变。

    package main
    import "fmt"
    
    func main() {
        var a=[7]int{1,2,3,4,5,6,7}
        var b[]int=a[2:6]
    
        fmt.Println(len(b))  //4
        fmt.Println(cap(b))  //5
        b=append(b,555)  //第一次追加
        b[0]=100
        fmt.Println(b)  //[100 4 5 6 555]
        fmt.Println(a)  //[1 2 100 4 5 6 555]
    
        b=append(b,666)   //第二次追加
        fmt.Println(len(b))    //6
        fmt.Println(cap(b))   //10
        b[0]=50
        fmt.Println(b)    //[50 4 5 6 555 666]
        fmt.Println(a)    //[1 2 100 4 5 6 555]
    }
    注意:变量b在最开始时候容量是5,在第二次追加之后长度为10,之前的容量5已经不够了,所以变成原来容量的两倍。超过了容量之后再追加不会再对原本的a数据进行修改

    切片的函数传递(当切片作为参数传递给函数时,函数内所做的更改也会在函数外可见)

    package main
    import "fmt"
    
    func main() {
        var b=make([]int,3,4)  #创建一个切片
        test(b)
        fmt.Println(b)
    }
    
    func test(b[]int)  {
        b[0]=999  #函数内修改切片
        fmt.Println(b)
    }
    
    #结果
    [999 0 0]
    [999 0 0]

    多维切片

    类似于数组,切片可以有多个维度

    package main
    import "fmt"
    
    func main() {
        var a[][]int=make([][]int,2,3)
        fmt.Println(a)      //[[] []]
        a[0]=make([]int,2,3)
        fmt.Println(a)      //[[0 0] []]
    }

    多维数组初始化并赋值

    package main
    import "fmt"
    
    func main() {
        var a [][]string=[][]string{{"1","2"},{"3","4"}}  
        fmt.Println(a)
        fmt.Println(len(a))
        fmt.Println(cap(a))
    
        a[0][1]="999"
        fmt.Println(a)
    
    }
    #结果
    [[1 2] [3 4]]
    2
    2
    [[1 999] [3 4]]
  • 相关阅读:
    【JZOJ5603】【NOI2018模拟3.27】Xjz
    【JZOJ5605】【NOI2018模拟3.26】Arg
    【agc004e】Salvage Robots
    【agc004c】AND Grid
    【agc004d】Teleporter
    【agc002f】Leftmost Ball
    【agc002d】Stamp Rally
    【arc068F】Solitaire
    51nod 1172 Partial Sums V2
    快速数论变换NTT模板
  • 原文地址:https://www.cnblogs.com/wangcuican/p/12019518.html
Copyright © 2020-2023  润新知