Go核心编程-数组 [Array]

2019-05-07  本文已影响0人  大鱼人Echo

为什么需要数组

案例1: 一个养鸡场有6只鸡,它们的体重分别是3kg,5kg,1kg,3.4kg,2kg,24kg。请问这6只鸡的总体重是多少?平均体重是多少?请你编写一个程序表示

传统写法

package main

import (
    "fmt"
)

// 一个养鸡场有6只鸡,它们的体重分别是3kg,5kg,1kg,3.4kg,2kg,24kg。请问这6只鸡的总体重是多少?平均体重是多少?请你编写一个程序表示
func main() {
    chick1 := 3.0
    chick2 := 5.0
    chick3 := 1.0
    chick4 := 3.4
    chick5 := 2.0
    chick6 := 24.0

    totalWeight := chick1 + chick2 + chick3 + chick4 + chick5 + chick6

    // fmt.Sprintf("%.2f", totalWeight / 6) "%.2f"表示 四舍五入保留到小数点返回值
    avgWeight := fmt.Sprintf("%.2f", totalWeight / 6)

    fmt.Printf("totalWeight=%v avgWeight=%v", totalWeight, avgWeight)
}

这种写法不太好的地方

  1. 使用传统方法不利于数据的管理与维护
  2. 传统的方法不够灵活,因此我们引入新的数据类型 => 数组

什么是数组

数组可以存放多个同一类型数据,数组也是一种数据类型,在Go中数组是值类型

我们可以使用数组来解决养鸡场的问题

package main

import (
    "fmt"
)

func main() {
    // 1. 定义一个数组
    var chicks [6]float64

    // 给数组的每个元素赋值, 元素的下标是从0开始的 0-5
    chicks[0] = 3.0
    chicks[1] = 5.0
    chicks[2] = 1.0
    chicks[3] = 3.4
    chicks[4] = 2.0
    chicks[5] = 24.0

    totalWeight := 0.0
    // 遍历数组求出总体重
    for i := 0; i < len(chicks); i++ {
        totalWeight += chicks[i]
    }

    // 求出平均值
    avgWeight := fmt.Sprintf("%.2f", totalWeight / float64(len(chicks)))

    fmt.Printf("totalWeight=%v avgWeight=%v", totalWeight, avgWeight)

}

使用数组的优点

  1. 使用数组来解决问题,程序的可维护性增加
  2. 方法代码更加清晰,也容易扩展

数组的定义和内存布局

数组的使用

案列1:从终端循环输入5个成绩,保存到float64数组,并输出

package main

import (
    "fmt"
)

func main() {

    var score [5]float64
    // 1. 从终端循环输入5个成绩, 保存到float64数组, 并输出
    for i := 0; i < len(score); i++ {
        fmt.Printf("请输入第%d个元素的值: ", i + 1)
        fmt.Scanln(&score[i])
    }

    // 2. 打印数组
    for i := 0; i < len(score); i++ {
        fmt.Printf("score[%d]=%v\n", i, score[i])
    }

    
}

数组的四种初始化方式

package main

import (
    "fmt"
)

// 四种初始化数组的方式
func main() {
    
    // 方式1
    var numArr1 [3]int = [3]int{1, 2, 3}
    fmt.Println("numArr1= ", numArr1)

    // 方式2
    var numArr2 = [3]int{5, 6, 7}
    fmt.Println("numArr2= ", numArr2)

    // 方式3
    // 这里的[...]是规定写法, 不定数组长度
    var numArr3 = [...]int{8, 9, 10}
    fmt.Println("numArr3= ", numArr3)
    
    // 方式4
    // 指定数组下标对应的值
    var numArr4 = [...]int{1: 800, 0: 900, 2:999}
    fmt.Println("numArr4= ", numArr4)

    // 类型推导
    strArr5 := [...]string{1: "tom", 0: "jack", 2: "Echo"}
    fmt.Println("strArr5= ", strArr5)
}

数组的遍历

  1. 常规遍历 如上

  2. for-range结构遍历

// 基本语法
for index, value := range strArr {

}

说明:

package main

import (
    "fmt"
)

func main() {

    // 1. 定义字符串数组
    heros := [...]string{"黄龙", "张康", "吴良材"}
    
    // 2. 使用for range 遍历
    for i, v := range heros {
        fmt.Printf("i=%v v=%v\n", i, v)
        fmt.Printf("heros[%d]=%v\n", i, heros[i])
    }

    // 3. 当不需要使用索引下标时可以使用_丢弃
    for _, v := range heros {
        fmt.Printf("元素的值=%v\n", v)
    }

}

数组使用的注意事项和细节

  1. 数组是有多个相同类型数据的组合, 一个数组一旦声明/定义了, 其长度是固定的,不能动态变化

  2. var arr []int 这时arr就是一个切片, 切片的概念后续章节会分享

  3. 数组中的元素可以是任何数据类型, 包括值类型和引用类型,但是不能混用

  4. 数组创建后, 如果没有赋值, 有默认值(零值)
    4.1 数值类型数组: 默认值为0
    4.2 字符串数组: 默认值为""
    4.3 bool数组: 默认值为false

  5. 使用数组的步骤
    5.1 声明数组并开辟空间
    5.2 给数组各个元素赋值(默认零值)
    5.3 使用数组

  6. 数组的下标是从0开始的

  7. 数组下标必须在指定范围内使用, 否则报panic: 数组越界
    比如 var arr[5]int 则有效下表为 0-4

  8. Go的数组属性类型, 在默认情况是值传递, 因此会进行值拷贝, 数组间不会相互影响

  9. 如果想在其他函数中, 去修改原来的数组, 可以使用引用传递(指针方式)

  10. 长度是数组类型的一部分, 在传递函数参数时需要考虑数组的长度, 具体看下面案例

数组应用案例

案例1: 创建一个byte类型的26个元素的数组, 分别放置'A'-'Z', 使用for循环访问所有元素并打印出来。 提示: 字符数据运算 'A' + 1 -> 'B'

package main

import (
    "fmt"
)

func main() {

    // 1. 定义一个字节数组长度为26
    var charArr [26]byte

    // 2. 利用 'A' + 1 -> B 的特性进行数组赋值
    for i := 0; i < len(charArr); i++ {
        charArr[i] = 'A' + byte(i)
    }

    for _, value := range charArr {
        // 3. 打印字符
        fmt.Printf("%c\t", value)
    }

}

案例2: 请求出一个数组的最大值, 并得到对应的下标

package main

import (
    "fmt"
)

func main() {
    // 1. 声明一个数组
    var intArr [6]int = [...]int{1, -1, 9, 90, 11, 9000}
    
    // 2. 假定第一个元素就是最大值, 下标就是0
    maxValue := intArr[0]
    maxValueIndex := 0

    // 3. 从第二个元素开始循环比较, 如果发现更大, 就交换
    for i := 1; i < len(intArr); i++ {
        if maxValue < intArr[i] {
            maxValue = intArr[i]
            maxValueIndex = i
        }
    }

    fmt.Printf("maxValueIndex: %d, maxValue: %d", maxValueIndex, maxValue)
}

案例3: 请求出一个数组的和和平均值 for-range

package main

import (
    "fmt"
)

func main() {
    // 1. 声明一个数组
    var intArr [5]int = [...]int{1, -1, 9, 90, 12}
    sum := 0

    // 2. 求出总和sum
    for _, value := range intArr {
        sum += value
    }

    // 3. 求出平均值
    // 让平均值保留到小数
    fmt.Printf("sum=%v, 平均值=%v", sum, float64(sum) / float64(len(intArr)))
}

案例4: 随机生成5个数, 并将其反转打印

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {

    var intArr [5]int;
    
    // 1. 随机生成五个数, rand.Intn() 函数

    // 为了每次生成的随机数不一样, 我们需要给一个seed值
    rand.Seed(time.Now().UnixNano())
    for i, _ := range intArr {
        intArr[i] = rand.Intn(100) // 随机数生成范围:0 <= n < 100
    }

    fmt.Println("交换前:", intArr)
    
    arrLength := len(intArr)
    
    // 2. 思路:倒数第1个和第1个元素交换, 倒数第2个和第2个袁术交换
    // 3. 交换次数是 arrLength / 2
    // 使用一个临时变量
    temp := 0
    for i := 0; i < arrLength / 2; i++ {
        temp = intArr[i]
        intArr[i] = intArr[arrLength - 1 - i]
        intArr[arrLength - 1 - i] = temp
    }

    fmt.Println("交换后:", intArr)
}
上一篇 下一篇

猜你喜欢

热点阅读