数组 Array
本教程共 93 篇 · 第 17 篇 · 更新于 2026-08-08 · 约 8 分钟阅读
本节目标:读完你能声明数组、往里增删改元素、用下标和循环访问,并理解数组越界会被 Swift 拦下。
数组是按顺序存放同一类型值的容器。同一个值可以出现在不同位置。它是 Swift 三种主要集合类型里最常用的一个。这一章把数组的日常用法系统过一遍。
1-1 数组的类型写法
数组的完整类型写法是 Array<元素>,但大家几乎都用简写 [元素]。两种等价,简写是主流。
var shoppingList: [String] = ["鸡蛋", "牛奶"]
这表示”一个只能装字符串的数组”。因为 Swift 类型安全,你没法把错误类型的值塞进去。
得益于类型推断,如果用同类型字面量初始化,连类型都能省:
var shoppingList = ["鸡蛋", "牛奶"] // 推断为 [String]
1-2 创建空数组
两种方式都能造空数组:
var empty1: [Int] = []
var empty2 = [Int]()
当上下文已能推断类型时,用空字面量 [] 最简洁。已填值的数组也能用 someInts = [] 重新清空,但类型不变,仍是 [Int]。
1-3 带默认值的数组
想造一个”同样的值重复 N 次”的数组,用 Array(repeating:count:):
var threeDoubles = Array(repeating: 0.0, count: 3)
// [0.0, 0.0, 0.0]
这在初始化占位数据、造棋盘、批量建默认项时很方便。
1-4 数组合并
两个同类型数组能用 + 直接合并成新数组:
var a = Array(repeating: 0.0, count: 3)
var b = Array(repeating: 2.5, count: 3)
var c = a + b // [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
合并后类型是推断出来的,和两边一致。
1-5 查数量与判空
用只读的 count 看元素个数,isEmpty 快速判断是否空:
print("清单有 \(shoppingList.count) 项")
if shoppingList.isEmpty {
print("清单是空的")
}
isEmpty 比 count == 0 更地道,可读性更好。
1-6 追加元素
往末尾加一项用 append(_:):
shoppingList.append("面粉")
也能用 += 追加另一个兼容数组,甚至一次加多个:
shoppingList += ["泡打粉"]
shoppingList += ["巧克力酱", "奶酪", "黄油"]
1-7 用下标访问与修改
方括号加下标就能取值,注意数组下标从 0 开始:
var first = shoppingList[0] // "鸡蛋"
shoppingList[0] = "六个鸡蛋" // 改第一项
还能用下标一次性替换一段范围,替换的长度可以和原来不同:
shoppingList[4...6] = ["香蕉", "苹果"]
这里把原来三项换成两项,数组长度随之变化。这种”范围赋值可改长度”的能力很灵活。
Warning数组下标必须有效。写
shoppingList[shoppingList.count] = "盐"试图在下标等于长度处追加会运行时崩溃——那个位置不存在。追加请用append。最大有效下标是count - 1。
1-8 插入与删除
在指定位置插一项用 insert(_:at:):
shoppingList.insert("枫糖浆", at: 0) // 插到最前面
删除指定下标项用 remove(at:),它返回被删的那项:
let removed = shoppingList.remove(at: 0)
删最后一项用 removeLast() 比 remove(at: count-1) 更省事,也避免再查一次长度。访问或删除越界下标都会触发运行时错误,所以操作前最好确认下标有效。
1-9 遍历数组
最常用 for-in 逐一看每个元素:
for item in shoppingList {
print(item)
}
如果同时想要”下标和值”,用 enumerated():
for (index, value) in shoppingList.enumerated() {
print("第 \(index + 1) 项:\(value)")
}
enumerated() 返回 “(下标, 值)” 的元组,解构后下标从 0 递增,正好对应真实下标。
1-10 数组的可变性
数组的可变性由 let/var 决定:赋给 var 就能增删改;赋给 let 就完全不可变(大小和元素都锁死)。
let fixed = ["a", "b"]
// fixed.append("c") 错误:常量数组不可变
官方建议:不需要变的数组就声明成 let,这样编译器能优化、读代码的人也知道它不会变。
1-11 多维数组
数组的元素本身可以是数组,于是有了二维(甚至更高维)数组,常用来表示矩阵、棋盘:
var board: [[Int]] = [
[1, 2, 3],
[4, 5, 6],
]
let topLeft = board[0][0] // 1
[[Int]] 读作”元素为 [Int] 的数组”,也就是”整数数组的数组”。访问时用两层下标。
1-12 数组的越界意识
数组是最常用的集合,把增删改查和”越界会被拦”这两点吃透,日常使用就稳了。声明用 [元素] 简写,类型推断让同类型字面量初始化时连类型都不用写。空数组 [] 或 [类型](),带默认值用 Array(repeating:count:),合并用 +。
count 看数量、isEmpty 判空、append/+= 追加、insert(at:) 插入、remove(at:) 删除,下标从 0 开始取值修改。范围下标还能一次替换一段,长度可不同——很灵活。但下标必须有效:写 list[list.count] = x 试图追加会崩溃,追加请用 append。
遍历用 for-in,要下标和值用 enumerated(),返回的 (下标, 值) 元组正好对应真实下标。可变性由 let/var 决定,官方建议不需要变的数组就声明成 let,编译器能优化、读代码的人也知道它不会变。多维数组用 [[元素]],两层下标访问。
越界是数组最常见的运行时错误。Swift 默认帮你检查下标,越界直接报错而非静默返回错误值——这是保护。所以操作前确认下标有效(比较 count),或用安全的方法如 first、last(返回可选值)。把”下标合法吗”当成条件反射,能省无数调试时间。
还有一个易混点:数组是值类型。赋给新变量或传参会拷贝(底层按需优化),所以你拿到的数组除非自己改,不会被别处改动。这和某些语言的”引用式数组”不同,理解这点,函数间传数组时才心里有底。数组的方法远不止这些(firstIndex、contains、sort、reverse 等都很常用),但本章的增删改查、遍历、越界意识是最核心的骨架。骨架稳了,遇到新需求查文档即可,不必死记每个方法。
1-13 补记:更安全的访问方法
补充两个实用方法。first 和 last 返回数组的首尾元素,类型是可选值(空数组时返回 nil),比用下标 array[0] 安全——后者在空数组时会崩溃。firstIndex(of:) 能查某个元素首次出现的下标,查不到返回 nil。这些方法都返回可选值,正是 Swift 逼你处理”可能不存在”的安全设计。
还有 contains(_:) 判断数组是否含某元素、sort() 原地排序、sorted() 返回新排序数组。数组方法很多,但万变不离其宗:可变操作改 var,查询操作返回新值或可选值。把”越界保护”和”可选值”这两条意识焊死,数组相关的 bug 会少一大半。
初学数组最容易犯的错,就是下标越界和误以为数组是引用。每次写下标前问自己”这个值一定存在吗”,基本就能避开绝大多数崩溃。
1-14 小结
数组 [元素] 按序存同类型值,下标从 0 开始。append/+= 追加、insert(at:) 插入、remove(at:) 删除、count/isEmpty 查状态。下标访问和修改都要保证有效,越界会被 Swift 拦下。遍历用 for-in,要下标用 enumerated()。常量数组不可变,推荐默认可不变。多维数组用 [[元素]]。下一章看集合 Set——只存不重复值的无序容器。