zoukankan      html  css  js  c++  java
  • slice

    package main
    
    import "fmt"
    
    func main() {
        /*
        slice :拥有相同类型元素的可变长的序列。 通常写成 []T,T是元素类型。
        slice和数组的关联:slice是一种轻量级的数据结构,可以用来访问数组的部分或者全部元素
            ,而这个数组成为slice的底层数组。一个底层数组可以对应多个slice
        slice三个属性:指针、长度、容量
            1 指针:指向数组的第一个可以从slice中访问的元素,并不一定是数组的第一个元素
            2 长度:slice中元素的个数,不能超过容量
            3 容量:从slice的起始元素到底层数组的最后一个元素间元素的个数
        定义:s[i,j]  s可以使数组也可以是指向数组的指针
        */
    
        //定义一个底层数组
        months:=[...]string{
            1:"January", 2:"February",3:"March",
            4:"April", 5:"May",6:"June",
            7:"July",8:"August",9:"September",
            10:"October",11:"November",12:"December"}
    
        Q2:=months[4:7] //创建slice Q2,引用的是months数组的4,5,6
        summer:=months[6:9]
        fmt.Println(Q2)   //  [April May June]    两个slice Q2 summer中都有June元素
        fmt.Println(summer)   //  [June July August]
    
        //遍历 取 相同元素
        for _,s:=range summer{
            for _,q:=range Q2{
                if s ==q{
                    /*%T 类型占位符 %v 值占位符 %d 整型占位符 %f 浮点型占位符
                    %c 字符占位符 %s 字符串占位符 %p指针占位符*/
                    fmt.Printf("%s appears in both
    ", s)
                }
            }
        }
        scap:=cap(summer)
        fmt.Println(scap)   //7
        //如果slice的引用超过了被引用对象的容量,即 cap(s),则宕机;如果超过了备用用对象的长度,及len(s),那么最终slice回避原slicec长
        //fmt.Println(summer[:20])   //宕机 超过了被引用对象的容量
        endlessSummer:=summer[:5]
        fmt.Println(endlessSummer)  // [June July August September October] 超过了备用用对象的长度
    
        /* 注意
        求字符串(string)子串操作 和 对字节slice([]byte)做slice 操作 是相似的,都协作x[m:n],都返回原始字节的一个子序列。
        同时,他们的底层引用方式一样,所以两个操作都是消耗常量时间。
        区别在于:如果x是字符串, x[m,n]返回的是一个字符串;
                如果x是字节slice([]byte) ,x[m,n]返回的是 字节slice ([]byte)
        */
    
        a:=[...]int{0,1,2,3,4,5}
    
        reverse(a[:])    // a[:] 标识引用了正式数组
        fmt.Println(a)   //[5 4 3 2 1 0]
        fmt.Printf("a格式:%T",a)
    
        // 将一个slice左移n个元素: 连续调用resverse三次
        s:=[]int{0,1,2,3,4,5}
        //向左移动两个元素
        reverse(s[:2])
        reverse(s[2:])
        reverse(s)
        fmt.Println(s) //[2 3 4 5 0 1]
        q:=[]int{0,1,2,3,4,5}
        //向右移动两个元素
        reverse(q[4:])
        reverse(q[:4])
        reverse(q)
        fmt.Println(q)
        /* 注意 数组a  slice s的初始化表达式区别。a是创建有固定长度的数组,s是创建指向数组的slice.。
                slice也是按照顺序指定元素,也可以按照索引来指定元素,或两者结合
                区别1 数组可以比较,slice无法比较,因此无法使用==来测试slic是否拥有相同的元素
                标准库里给处理函数 bytes.Equal来比较两个字节slice([]byte).对于其他的
                slice,我们必须自己写函数比较
                区别2 slice的元素是间接的,如果底层数组的元素改变,sliced的元素原会改变
                slice唯一允许的比较操作就是和nil作比较:例如
                if summer == nil{......}
                slice 零值是 nil,值为nil的slice没有对应的底层数组,长度和容量都为零
        */
        // p:=[]int{1:1,0:0,3,4} 两者结合 报错.slices.go:73:19: duplicate index in array literal: 1
        p:=[]int{1:1,0:0,3:3,4}  //两者结合 ok  [0 1 0 3 4]
        fmt.Println(p)
        fmt.Printf("%T",p)
    
    
        /*内置函数 make
        作用:创建一个具有制定元素类型、长度和容量的slice。容量可以省略,此时,slice的长度与容量相等
        */
        sm:=make([]int,8)
        println(sm)
    }
    
    func reverse(s []int)  {
        // 初始值i,j:=0,len(s)-1  条件 i<j 表达式 i,j=i+1,j-1
        for i,j:=0,len(s)-1;i<j;i,j=i+1,j-1{
            s[i],s[j]=s[j],s[i]
        }
    
    }

     append()函数

    package main
    
    import "fmt"
    
    func main() {
        //rune类型 http://c.biancheng.net/view/18.html
        var runes []rune
        /*append函数
        作用:将元素追加到slice后面
        通常将append的调用结果再次复制给传入applend函数的slice,更新slice变量
        对于任何函数,只要有可能改变slice的长度或者容量,或者使slice指向不同的底层数组
        都需要更新slice变量
        */
        for _,r:=range "good"{
            runes=append(runes,r)
        }
        fmt.Printf("%q
    ",runes) //['g' 'o' 'o' 'd']
    
    
        var x,y []int
        for i:=0;i<10;i++{
            y=appendInt(x,i)
            fmt.Printf("%d cap=%d	%v
    ",i,cap(y),y)
            x=y
        }
    
    
    }
    
    
    //为[]int数组slice定义方法appendInt
    
    func appendInt(x []int,y int) []int {
        var z []int
        zlen := len(x)+1
        //检查slice是否有足够容量来存储数组中的新元素
        if zlen <= cap(x){
            z=x[:zlen]  //有足够的容量则 定义新的slice(底层数组未变),将元素y复制到新位置
        }else{
            /*slice已无空间,为他分配新的底层数组,不够长则创建一个足够长的新的底层数组来存储新元素,
            增加两倍的目的是为了达到分摊线性复杂性
            */
            /*出于效率考录,新创建的数组容量会比实际容纳slice x slice y 所需的最小长度更大一i但。
            在每次数组容量扩容是,通过扩展已被的容量来减少内存分配的次数,也可以保证追加一个元素消耗的
            是固定时间
            每次slice容量的改变都意味着一次底层数组重新分配和元素复制
            */
            zcap:=zlen
            if zcap<2*len(x){
                zcap=2*len(x)
            }
            z=make([]int,zlen,zcap)   //定义新的slice
            /*内置copy函数:为两个相同类型元素的slice复制元素 copy(目标slice,源slice)
                    copy()的返回值是实际复制的元素个数,是较小的slice的长度
    
            var a=[]int{1,2,3,5,8,7,10}
            var b=[]int{1,2,3,4,6,10}
            d:=copy(b,a)
            fmt.Println(d)   //6
            fmt.Println(b)   //[1 2 3 5 8 7]
    
            所以不存在复制导致的索引越界
            */
            copy(z,x)
    
        }
        z[len(x)]=y
        return z
    
    }

     就地更改slice

    package main
    
    import "fmt"
    
    func main()  {
        data:=[]string{"one","","three"}
        fmt.Printf("%q
    ",nonemty(data)) //["one" "three"]
        fmt.Printf("%q
    ",data) //["one" "three" "three"]
    
    
        s:=[]int{5,6,7,8,9}
        fmt.Println(remove(s,2))  // [5 6 8 9]
    }
    
    //输入和输出有相同的底层数组,避免在函数内部重新分配一个数组,底层数组的元素被部分修改
    func nonemty(strings []string) []string {
        i:=0
        for _,s:=range strings{
            if s!=""{
                strings[i]=s
                i++
            }
        }
        return strings[:i]
    
    }
    //移除slice中的某个元素,保持原来的顺序不变
    func remove(slice []int,i int) []int  {
        //copy 把第二个切片的元素赋值copy到第一个切片总
        copy(slice[i:],slice[i+1:])
        return slice[:len(slice)-1]
    
    }
  • 相关阅读:
    cg纹理绑定顺序的一个错误
    难道一直是4 4 2 3的命?
    cg又一个数据绑定错误
    cg fp40的问题
    bibtex to bibitem
    qt ogl添加keyevent
    支付宝开发
    jQuery ajax的提交
    Java链接MySQL数据库的配置文件
    excel 函数的引用说明
  • 原文地址:https://www.cnblogs.com/Hale-wang/p/13561198.html
Copyright © 2011-2022 走看看