golang基础06: 一场选秀活动,让你彻底掌握数组和切片的用法

admin 2024年2月16日11:18:41评论10 views字数 4605阅读15分21秒阅读模式

数组是一组具有相同类型的元素的集合,它们在内存中是连续存储的。数组的长度是固定的,一旦声明后无法改变 。

切片是对数组的抽象,它提供了更灵活的方式来操作数据。切片是一个动态大小的、可以自动扩容的序列。

结构体是一种自定义数据类型,可以封装多个基本数据类型。

选秀活动

某个选秀活动,有三个参赛选手,到会场的观众N个,观众给心仪的选手打分,计算总分数,并获得排名

golang基础06: 一场选秀活动,让你彻底掌握数组和切片的用法

首先我们定义选手的结构体

type Player struct {  Name  string   // 姓名  Score int      // 得分}

三个选手来到活动现场后,我们要先明确选手,这样我们就定义Player的数组

// 定义一个数组表示三人信息var player [3]Player// 三个选手到位、分别是小张、小李、小王、分数为0player[0] = Player{Name: "小张", Score: 0}player[1] = Player{Name: "小李", Score: 0}player[2] = Player{Name: "小王", Score: 0}

下面是观众了,整场活动现在最大坐席容量为1000人,因为活动方不关心观众的信息,仅关注手中的票投给谁。而且出席观众多少也未知。

// 最大容量max := 1000// 定义观众,所以我们就定义一个整型切片var viewers []int// 到场的随机观众数n := rand.Intn(max)// 前面说了切片有容量,我们给切片开辟n的容量viewer = make([]int, n)// 给每个观众发送票for i := 0; i < n; i++ {    viewer[i] = 1}

准备工作完成后,我们就可以给选手投票,每个选手上台,展示才艺,观众给投票,要经过3轮

// 选手登场for i, p := range player {    // 临时记录选手得分    score := 0    // 观众给选手打分    for n, v := range viewer {        // 观众手中没票了就失去投票的权利        if v == 0 {            continue        }        // 0、1的随机数 是否投给选手        s := rand.Intn(2)        // 观众手中票投出        viewer[n] = v - s        // 统计某选手总分        score += s    }    // 把观众投的总分数给选手    p.Score = score    // 更新选手信息    player[i] = p}

现在经过3轮角逐完成,现在激动人心的时候到了。就是统计所有选手所得分

// 要做排序处理,golang中有对slice排序的函数,可以直接使用// 素组转化为slicecal := player[:]// 对临时slice排序sort.SliceStable(cal, func(i, j int) bool {    return cal[i].Score > cal[j].Score})

最后,公示所有选手得分,并决出冠军

fmt.Printf("本场活动总出席观众:%drn", len(viewer))  for i, p := range cal {    fmt.Printf("第%d名 姓名:%s 分数:%drn",     i+1,     p.Name,     p.Score)  }

下面是整体代码,创建main.go文件,写入下面内容

package mainimport (  "fmt"  "math/rand"  "sort")type Player struct {  Name  string  Score int}func main() {  var max int = 1000  var player [3]Player  player[1] = Player{Name: "小李", Score: 0}  player[2] = Player{Name: "小王", Score: 0}  player[0] = Player{Name: "小张", Score: 0}  var viewer []int  // 到场的随机观众数  n := rand.Intn(max)  viewer = make([]int, n+1)  // 给每个观众发送票  for i := 0; i <= n; i++ {    viewer[i] = 1  }  // 开始投票  for i, p := range player {    score := 0    for n, v := range viewer {      // 选观众中没票了就失去投票的权利      if v == 0 {        continue      }      // 是否投给选手      s := rand.Intn(2)      // 观众手中票投产      viewer[n] = v - s      // 统计某选手总分      score += s    }    // 把观众投给她的总票数赋值给选手    p.Score = score    // 更新选手信息    player[i] = p  }  // 统计选手票,并做排名  cal := player[:]  sort.SliceStable(cal, func(i, j int) bool {    return cal[i].Score > cal[j].Score  })  fmt.Printf("本场活动总出席观众:%d人rn", len(viewer))  for i, p := range cal {    fmt.Printf("第%d名 姓名:%s 分数:%drn", i+1, p.Name, p.Score)  }}

go run main.go 运行程序,结果 如下:

本场活动总出席观众:357第1名 姓名:小张 分数:173第2名 姓名:小李 分数:101第3名 姓名:小王 分数:45

数组和切片的基本使用

数组和切片变量的声明、初始化、赋值等方式

// 声明数组var arr [3]string// 初始化arr = [3]string{"xiaoli","xiaozhang","xiaowang"}// 声明并初始化,下面三种定义数组方式作用相同var arr1 [3]string = [3]string{"xiaoli","xiaozhang","xiaowang"}// 声明并初始化:数组容量和类型根据初始化决定var arr2 =  [...]string{"xiaoli","xiaozhang","xiaowang"}// 声明并初始化arr3 :=  [3]string{"xiaoli","xiaozhang","xiaowang"}// 声明切片var sli []string// 初始化sli = []string{"xiaoli","xiaozhang","xiaowang"}// 声明并赋值var sli1 []string = [3]string{"xiaoli","xiaozhang","xiaowang"}// 声明并初始化:切片长度和容量类型根据初始化决定var sli2 =  []string{"xiaoli","xiaozhang","xiaowang"}// 声明并初始化sli3 :=  []string{"xiaoli","xiaozhang","xiaowang"}// 切片扩容赋值,定义长度2,容量3sli4 := make([]int,2,3)sli4[0] = 1sli4[1] = 2// 由于定义的长度为2,下面语句是错误// 运行 runtime error: index out of range [2] with length 2// sli4[2] = 3

数组是值拷贝、而切片是引用类型

// 声明数组  var arr [3]string  // 初始化  arr = [3]string{"xiaoli", "xiaozhang", "xiaowang"}  funcArr := func(arr [3]string) [3]string {    arr[0] = "edit"    return arr  }  arr1 := funcArr(arr)  fmt.Printf("arr 的指针:%p,arr的值:%v n", &arr, arr)  fmt.Printf("arr1 的指针:%p,arr1的值:%v n", &arr1, arr1)  sli := []string{"xiaoli", "xiaozhang", "xiaowang"}  funcSlic := func(sli []string) []string {    sli[0] = "edit2"    return sli  }  sli1 := funcSlic(sli)  fmt.Printf("sli 的指针:%p,sli的值:%v n", &sli, sli)  fmt.Printf("sli1 的指针:%p,sli1的值:%v n", &sli1, sli1)}// 输出结果,在funcArr中复值拷贝,未改变数组值,切片funcSlic把sli和sli1的值改成了edit2// arr 的指针:0xc0000200f0,arr的值:[xiaoli xiaozhang xiaowang]// arr1 的指针:0xc000020120,arr1的值:[edit xiaozhang xiaowang]// sli 的指针:0xc000008048,sli的值:[edit2 xiaozhang xiaowang]// sli1 的指针:0xc000008060,sli1的值:[edit2 xiaozhang xiaowang]

数组转切片

a := [3]int{1,2,3,4}// 截取数组为切片长度和容量都等于结束索引-开始索引a1 := a[1:3] // 索引1,2左闭右开fmt.Println(a1, len(a1), cap(a1))// [2 3] 2 2

上面代码底层执行逻辑

golang基础06: 一场选秀活动,让你彻底掌握数组和切片的用法

切片扩容

// 切片扩容赋值,定义长度和容量sli4 := make([]int, 2, 3)sli4[0] = 1sli4[1] = 2fmt.Println(sli4, len(sli4), cap(sli4))sli4 = append(sli4, 5)fmt.Println(sli4, len(sli4), cap(sli4))sli4 = append(sli4, []int{7, 8, 9}...)fmt.Println(sli4, len(sli4), cap(sli4))// 查看输出结果// [1 2] 2 3// [1 2 5] 3 3// [1 2 5 7 8 9] 6 6

切片的常用截取

// 将切片 b 的元素追加到切片 a 之后a := make([]int,1)b :== []int{1,2,3}a = append(a, b...)// 复制切片 a 的元素到新的切片 c 上c := make([]int, len(a))copy(c, a)// 删除位于索引 i 的元素,a[:i]0至i-1元素,把a[i+1:]i+1索引到结尾的追加到子切片a[:i]后a = append(a[:i], a[i+1:]...)// 切除切片 a 中从索引 i 至 j 位置的元素a = append(a[:i], a[j:]...)// 为切片 a 扩展 j 个元素长度a = append(a, make([]int, j)...)// 在索引 i 的位置插入元素 3a = append(a[:i], append([]int{3}, a[i:]...)...)// 在索引 i 的位置插入长度为 3 的新切片a = append(a[:i], append(make([]int, 3), a[i:]...)...)// 索引 i 的位置插入切片 b 的所有元素a = append(a[:i], append(b, a[i:]...)...)// 取出位于切片 a 最末尾的元素 xx := a[len(a)-1]

在我们写代码的过程中,常用切片处理一些同数据类型数据。切片并不直接持有数据,而是引用底层数组的一部分。所以我们这章核心内容就是切片。

更多课程文章一步步带你轻松搭建Go开发环境
运算符、数值类型和输入输出
golang基础03:动手实现聊天机器人
golang基础04: 控制流的使用示例
golang基础05:循环和迭代示例
golang开发工资自发送小软件

原文始发于微信公众号(数据安全治理技术):golang基础06: 一场选秀活动,让你彻底掌握数组和切片的用法

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月16日11:18:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   golang基础06: 一场选秀活动,让你彻底掌握数组和切片的用法http://cn-sec.com/archives/2157854.html

发表评论

匿名网友 填写信息