zoukankan      html  css  js  c++  java
  • 切片

    • 切片的英文名称slice

    • 切片:具有可变长度相同类型元素序列.

    • 由于长度是可变,可以解决数组长度在数据个数不确定情况下浪费内存的问题.

    • 切片和数组声明时语法最主要的区别就是长度

        var slice []string  //切片
        var array [3]string //数组
    • 切片只声明时为nil,没有开辟内存空间,不能直接操作切片,需要先初始化

      • 注意:切片只能和nil进行判断是否相等

        var slice []string  //切片
        fmt.Println(slice==nil)//输出:true
        fmt.Printf("%p",slice)//输出:0x0

    定义切片

    • 通过直接指定初始值定初始化一个切片变量

        names := []string{"smallming", "abcd"}
        fmt.Println(names)
    • 定义完切片后就可以通过切片对象[脚标]取出或修改切片中元素内容.语法和数组相同

    切片是引用类型

    • 引用类型在变量之间赋值时传递的是地址.引用类型变量就是这个类型的指针.切片就是引用类型

    • 值类型在变量之间赋值时传递的是值的副本

        names := []string{"smallming", "abcd"}
        names1 := names
        names1[0] = "efg"
        fmt.Println(names, names1)
        fmt.Printf("%p %p",names,names1)//地址相同

    make函数

    • Go语言中可以使用make函数创建slice 、 map、 channel、 interface

    • 使用make函数定义无内容,但是不是nil的切片,意味着切片已经申请了内存空间

      • make(类型,初始长度[,初始容量])

      • 初始容量可以省略,默认和长度相等

        slice := make([]string, 0)     //长度为0的切片,没有第三个参数表示容量和长度相等
        slice1 := make([]string, 0, 2) //长度为0,容量为2
        fmt.Println(slice, slice1)
    • 长度表示切片中元素的实际个数,容量表示切片占用空间大小,且切片容量成倍增加.当增加到1024后按照一定百分比增加.

      • len(slice) 查看切片的长度

      • cap(slice) 查看切片的容量

        slice := make([]string, 0)     //长度为0的切片,没有第三个参数表示容量和长度相等
        slice1 := make([]string, 0, 3) //长度为0,容量为3
        fmt.Println(len(slice), cap(slice))
        fmt.Println(len(slice1), cap(slice1))

    append()函数

    • 可以向切片中添加一个或多个值,添加后必须使用切片接收append()函数返回值
        s := make([]string, 0)
        fmt.Println(len(s), cap(s))//输出:0 0
        s = append(s, "1", "2")
        fmt.Println(len(s), cap(s))//输出:2 2
        s = append(s, "smallming")
        fmt.Println(len(s), cap(s))//输出:3 4
    • 如果添加一次添加多个值,且添加后的长度大于扩容一次的大小,容量和长度相等.等到下次添加内容时如果不超出扩容大小,在现在的基础上进行翻倍
        s := make([]string, 0)
        fmt.Println(len(s), cap(s)) //输出:0 0
        s = append(s, "1", "2")
        fmt.Println(len(s), cap(s)) //输出:2 2
        s = append(s, "smallming")
        fmt.Println(len(s), cap(s)) //输出:3 4
        s = append(s, "4", "5", "6", "7", "8", "9")
        fmt.Println(len(s), cap(s)) //输出:9 9
        s = append(s,"10")
        fmt.Println(len(s), cap(s)) //输出:10 18
    • 也可以把一个切片的内容直接添加到另一个切片中.需要注意语法中有三个点
        s := make([]string, 0)
        s1 := []string{"smallming", "123"}
        s = append(s, s1...) //注意此处,必须有三个点
        fmt.Println(s)

    通过数组产生切片

    • 定义数组后,取出数组中一个片段,这个片段就是切片类型

        names := [3]string{"a", "b", "c"}
        s := names[0:2]     //包前不包后
        fmt.Printf("%T", s) //输出:[]string
        fmt.Println(s)      //输出:[a b]
    • 切片是指针,指向数组元素地址,修改切片的内容,数组的内容会跟随变化
        names := [3]string{"a", "b", "c"}
        s := names[0:2] //包前不包后
        fmt.Printf("%p %p",s,&names[0])//输出的地址是相同的
        s[0] = "Go语言"
        fmt.Println(s)     //输出:[Go语言 b]
        fmt.Println(names) //输出:[Go语言 b c]
    • 当切片内容在增加时

      • 如果增加后切片的长度没有超出数组,修改切片也是在修改数组

      • 如果增加后切片的长度超出数组,会重新开辟一块空间放切片的内容

      • 通过下面代码也正面了切片中内容存在一块连续空间(和数组一样)

        names := [3]string{"a", "b", "smallming"}
        s := names[0:2] //包前不包后
        fmt.Printf("%p %p
    ",s,&names[0])
        s[0] = "Go语言"
        s=append(s,"区块链")
        fmt.Println(s)     //输出:[Go语言 b 区块链]
        fmt.Println(names) //输出:[Go语言 b 区块链]
        fmt.Printf("%p %p
    ",s,&names[0])//地址相同
    
        s=append(s,"超出了数组长度")
        fmt.Println(s)     //输出:[Go语言 b 区块链 超出了数组长度]
        fmt.Println(names) //输出:[Go语言 b 区块链]
        fmt.Printf("%p %p
    ",s,&names[0])//切片地址改变

    删除实现

    • Go语言标准库中没有提供删除的函数

    • 切片也可以取其中的一段形成子切片,利用这个特性可以实现删除效果

        num := []int {0,1,2,3,4,5,6}
        //要删除脚标为n的元素
        n:= 2
        num1 :=num[0:n]
        num1= append(num1,num[n+1:]...)
        fmt.Println(num1)

    copy函数

    • 通过copy函数可以把一个切片内容复制到另一个切片中

    • Go语言标准库源码定义如下

      • 第一个参数是目标切片,接收第二个参数内容

      • 第二个参数是源切片,把内容拷贝到第一个参数中

    // The copy built-in function copies elements from a source slice into a
    // destination slice. (As a special case, it also will copy bytes from a
    // string to a slice of bytes.) The source and destination may overlap. Copy
    // returns the number of elements copied, which will be the minimum of
    // len(src) and len(dst).
    func copy(dst, src []Type) int
    • 拷贝时严格按照脚标进行拷贝.且不会对目标切片进行扩容

    代码示例

    • 把短切片拷贝到长切片中

        s1:=[]int {1,2}
        s2:=[]int {3,4,5,6}
        copy(s2,s1)
        fmt.Println(s1)//输出:[1 2]
        fmt.Println(s2)//输出:[1 2 5 6]
    • 把长切片拷贝到短切片中
        s1:=[]int {1,2}
        s2:=[]int {3,4,5,6}
        copy(s1,s2)
        fmt.Println(s1)//输出:[3 4]
        fmt.Println(s2)//输出:[3 4 5 6]
    • 把切片片段拷贝到切片中
        s1:=[]int {1,2}
        s2:=[]int {3,4,5,6}
        copy(s1,s2[1:])
        fmt.Println(s1)//输出:[4 5]
        fmt.Println(s2)//输出:[3 4 5 6]

    使用copy完成删除元素

    • 使用copy函数可以保证原切片内容不变

        s := []int{1, 2, 3, 4, 5, 6, 7}
        n := 2 //要删除元素的索引
        newSlice := make([]int, n)
        copy(newSlice, s[0:n])
        newSlice = append(newSlice, s[n+1:]...)
        fmt.Println(s)        //原切片不变
        fmt.Println(newSlice) //删除指定元素后的切片

    sort包

    • Go语言标准库中sort提供了排序API

    • sort包提供了多种排序算法,这些算法是内部实现的,每次使用sort包排序时,会自动选择最优算法实现

      • 插入排序

      • 快速排序

      • 堆排

    • sort包中最上层是一个名称为Interface的接口,只要满足sort.Interface类型都可以排序

    // A type, typically a collection, that satisfies sort.Interface can be
    // sorted by the routines in this package. The methods require that the
    // elements of the collection be enumerated by an integer index.
    type Interface interface {
        // Len is the number of elements in the collection.
        Len() int
        // Less reports whether the element with
        // index i should sort before the element with index j.
        Less(i, j int) bool
        // Swap swaps the elements with indexes i and j.
        Swap(i, j int)
    }
    • Go语言标准库默认提供了对int、float64、string进行排序的API

    • 很多函数的参数都是sort包下类型,需要进行转换.

    排序实现

    • 对int类型切片排序

        num := [] int{1, 7, 5, 2, 6}
        sort.Ints(num) //升序
        fmt.Println(num)
        sort.Sort(sort.Reverse(sort.IntSlice(num))) //降序
        fmt.Println(num)
    • 对float64类型切片排序
        f := [] float64{1.5, 7.2, 5.8, 2.3, 6.9}
        sort.Float64s(f) //升序
        fmt.Println(f)
        sort.Sort(sort.Reverse(sort.Float64Slice(f))) //降序
        fmt.Println(f)
    • 对string类型切片排序

      • 按照编码表数值进行排序

      • 多字符串中按照第一个字符进行比较

      • 如果第一个字符相同,比较第二个字符

        s := []string{"", "我是中国人", "a", "d", "国家", "", "我a"}
        sort.Sort(sort.StringSlice(s)) //升序
        fmt.Println(s)
        //查找内容的索引,如果不存在,返回内容应该在升序排序切片的哪个位置插入
        fmt.Println(sort.SearchStrings(s, "你是"))
        sort.Sort(sort.Reverse(sort.StringSlice(s)))
        fmt.Println(s)
  • 相关阅读:
    2019计蒜之道初赛第三场题解
    牛客小白月赛14 :部分题目总结
    CF-558:部分题目总结
    浙江省第十六届大学生ACM程序设计竞赛部分题解
    浙江省高职院校联合训练(一)
    CF-544:部分题目总结
    CF-552E-Two Teams
    CF-551:部分题目总结
    freemarker使用map替换字符串中的值
    freemarker使用map替换ftl中相关值
  • 原文地址:https://www.cnblogs.com/miaoweiye/p/12091507.html
Copyright © 2011-2022 走看看