(头歌)GO slice关卡解答

​​​​​​


任务描述

请用户实现一个名为slice_add的函数,要求该函数能合并两个slice的全部元素到一个新的slice,并返回新slice的长度len和容量cap

相关知识

Go 语言数组我们在之前的实训中已经学习过,那个实训曾经提过一句话:切片slice类型构建于数组之上,所以掌握数组是后面学习slice的基础。本关我们继续讲一下数组,让学员更好地理解数组和slice的区别。

数组和slice的区别

Go 语言中数组是具有固定长度而且拥有零个或者多个相同或相同数据类型元素的序列。由于数组长度固定,所以在 Go 语言比较少直接使用。而slice长度可增可减,使用场合比较多。更深入的区别在于:数组在使用的过程中都是值传递,将一个数组赋值给一个新变量或作为方法参数传递时,是将源数组在内存中完全复制了一份,而不是引用源数组在内存中的地址。为了满足内存空间的复用和数组元素的值的一致性的应用需求,slice出现了,每个slice都是都源数组在内存中的地址的一个引用,源数组可以衍生出多个slice,slice也可以继续衍生其他slice

数组

Go 语言数组中每个元素是按照索引来访问的,索引从 0 到数组长度减 1 。Go 语言内置函数len可以返回数组中的元素个数。

数组定义初始化

初始化方式有四种:指定/不指定长度*初始化部分/全部元素两两组合。示例代码如下:

 
  1. var a [3] int //3个整数型的数组,初始值是3个0
  2. arr:=[5]int{1,2,3,4,5} //长度为5
  3. var array2 = [...]int{6, 7, 8} //不声明长度
  4. q := [...] int {1,2,3} //不声明长度
  5. r := [...] int {99:-1} //长度为100的数组,只有最后一个是-1,其他都是0

数组作为函数参数

Go语言中数组也可以作为参数:

 
  1. package main
  2. import "fmt"
  3. func modify_arr(array [5]int) {
  4. array[0]=10
  5. fmt.Println("In modify_arr,array values is:",array)
  6. }
  7. func main() {
  8. arr:=[5]int{1,2,3,4,5}
  9. modify_arr(arr)
  10. fmt.Println("In main,array values is:",arr)
  11. }

slice

Go 语言中数组是值类型,长度不可伸缩;而slice是引用类型,长度可动态增长。

slice概念

Go 语言中,slice表示一个拥有相同类型元素的可变长度序列。slice通常被写为[]T,其中元素的类型都是T;它看上去就像没有长度的数组类型。
数组和slice其实是紧密关联的。slice可以看成是一种轻量级的数据结构,可以用来访问数组的部分或者全部元素,而这个数组称之为slice的底层数组。slice有三个属性:指针,长度和容量。指针指向数组的第一个可以从slice中访问的元素,这个元素不一定是数组的第一个元素。长度指的是slice中的元素个数,不能超过slice的容量。指针通常是从指向数组的第一个可以从slice中访问的元素,这个元素不一定是数组的第一个元素。长度指的是slice中的元素个数,它不能超过slice的容量。容量的大小通常大于等于长度,会随着元素个数增多而动态变化。Go 语言的内置函数lencap用来返回slice的长度和容量。

slice定义初始化

slice初始化依赖于数组,可见如下代码和注释:

 
  1. s1 := []int{1, 2, 3} //注意与数组初始化的区别,在内存中构建一个包括有3个元素的数组,然后将这个数组的应用赋值给s这个slice
  2. a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0} //a是数组
  3. s2 := a[2:8] //从数组中切片构建slice
  4. s3 := make([]int, 10, 20) //make函数初化,len=10,cap=20

其中a是数组 ,s1,s2,s3slice

slice中len和cap关系

Go 语言的内置函数lencap用来返回slice的长度和容量。在追加元素时,如果容量cap不足时,cap一般变为原来的 2 倍来实现扩容。

slicecap扩容规则:

  • 如果新的cap大小是当前cap的 2 倍以上,则直接扩容为这个新的cap
  • 否则循环以下操作:如果当前cap小于1024,按每次 2 倍增长,否则每次按当前大小 1/4 增长。直到增长的大小超过或等于新的cap

slice一般用append函数追加元素,append第一个参数是slice,第二个参数是元素。示例代码如下:

 
  1. package main
  2. import "fmt"
  3. func print_info(my_slice[]int) {
  4. fmt.Println("len :",len(my_slice))
  5. fmt.Println("cap :",cap(my_slice))
  6. for i,v :=range my_slice{
  7. fmt.Println("element[",i,"]=",v)
  8. }
  9. }
  10. func main() {
  11. my_slice01:=[]int{1,2,3,4,5}
  12. my_slice02:=make([]int,5)
  13. my_slice03:=make([]int,5,6)
  14. my_slice04:=append(my_slice03,8,9,10)
  15. print_info(my_slice01)
  16. print_info(my_slice02)
  17. print_info(my_slice03)
  18. print_info(my_slice04)
  19. }

slice作为函数参数

注意和数组作为函数参数的区别:

 
  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. a := []int{1, 2, 3, 4, 5}
  7. var b = a[0:3]
  8. var c = [...]int{3, 6, 9, 2, 6, 4}
  9. d := c[0:2]
  10. sliceInfo(b)
  11. fmt.Printf("sum of b is %d\n", sum(b))
  12. fmt.Printf("sum of d is %d\n", sum(d))
  13. }
  14. func sum(a []int) int {
  15. s := 0
  16. for i := 0; i < len(a); i++ {
  17. s += a[i]
  18. }
  19. return s
  20. }
  21. func sliceInfo(x []int) {
  22. fmt.Printf("len is %d ,cap is %d, slice is %v\n", len(x), cap(x), x)
  23. }

slice的不可比性

Go 语言中slice map ,func一样,不支持 == 操作符,就是不能直接比较,唯一合法的就是和nil作比较。开发中经常会遇到需要比较两个slice包含的元素是否完全相等的情况,这个时候只能遍历两个 slice中的所有元素 ,看它们是否完全相等。

编程要求

本关的编程任务是在slice_func.go文件中实现一个名为slice_add的函数,补全Begin-End之间的代码,要求该函数能合并两个slice,并返回新slice的长度len和容量cap

本关涉及的代码文件sub_multi.go的代码如下:

 
  1. package main
  2. import (
  3. "fmt"
  4. )
  5. //请在此自定义一个名为slice_add的函数,
  6. //要求该函数能合并两个slice,并返回新slice的长度len和容量cap。
  7. //提示:结合之前学的函数不定参数
  8. /********* Begin *********/
  9. /********* End *********/
  10. func main() {
  11. s1 := []int{1, 2, 3, 4}
  12. s2 := []int{1, 2, 3, 4, 5}
  13. c,d := slice_add(s1,s2)
  14. fmt.Println(c)
  15. fmt.Println(d)
  16. }

评测说明

本关卡的测试文件是slice_func.go,具体测试过程如下:

1.平台自动编译生成slice_func.exe; 2.平台运行slice_func.exe; 3.获取slice_funci.exe输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。

预期输入:
预期输出:

 
  1. 9
  2. 10

提示:append的第一个参数是slice,第二个参数是元素。结合下我们之前学的函数不定参数,学员可以思考下如何用append()函数实现两个slice的合并。

答案:

package main

import (
    "fmt"
)


    //请在此自定义一个名为slice_add的函数,
	//要求该函数能合并两个slice,并返回新slice的长度len和容量cap。
	//提示:结合之前学的函数不定参数
    /********* Begin *********/
    func slice_add(s1,s2 []int)(int,int){
        newslice:=append(s1,s2...)
        return len(newslice),cap(newslice)
    }

    /********* End *********/

func main() {
	s1 := []int{1, 2, 3, 4} 
	s2 := []int{1, 2, 3, 4, 5}
    c,d := slice_add(s1,s2)
    fmt.Println(c)
    fmt.Println(d)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桂亭亭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值