Swift 数组(Array)全解析(2025 版)
“Array 是值类型、有序集合、类型安全” —— 掌握 60+ 操作,写出 高效、安全、函数式 的数组代码!
一、Swift 数组核心特性
| 特性 | 说明 |
|---|---|
| 值类型 | 赋值时复制,线程安全 |
| 有序 | 元素有固定顺序 |
| 同构 | 所有元素类型相同 |
| 动态大小 | 可增删元素 |
| 类型推断 | [Int], [String] 等 |
let numbers = [1, 2, 3] // [Int]
var fruits = ["苹果", "香蕩"] // [String]
二、创建数组
1. 字面量
let empty: [Int] = []
let zeros = Array(repeating: 0, count: 5) // [0,0,0,0,0]
let range = Array(1...5) // [1,2,3,4,5]
2. 类型推断
let scores = [95, 88, 70] // [Int]
let names = ["张三", "李四"] // [String]
3. 显式声明
var mutable: [Double] = []
let immutable: [String] = ["Swift"]
三、访问元素
let fruits = ["苹果", "香蕩", "橙子"]
// 下标访问
fruits[0] // "苹果"
fruits[1] // "香蕩"
// 安全访问
fruits.first // Optional("苹果")
fruits.last // Optional("橙子")
fruits[safe: 1] // 自定义安全下标(见后文)
// 范围取子数组
fruits[1...] // ["香蕩", "橙子"]
fruits[..<2] // ["苹果", "香蕩"]
fruits[1..<3] // ["香蕩", "橙子"]
四、修改数组(var)
var list = ["A", "B"]
// 添加
list.append("C")
list += ["D", "E"]
list.insert("X", at: 0)
// 删除
list.remove(at: 1) // 删除 "B"
list.removeLast() // 删除最后一个
list.removeAll() // 清空
// 替换
list[0] = "Z"
list[1...2] = ["P", "Q"] // 替换范围
五、常用属性
| 属性 | 说明 |
|---|---|
.count | 元素个数 |
.isEmpty | 是否为空 |
.first | 第一个元素(Optional) |
.last | 最后一个元素(Optional) |
.capacity | 当前容量 |
list.count // 5
list.isEmpty // false
六、遍历数组
1. for-in
for fruit in fruits {
print(fruit)
}
// 带索引
for (index, fruit) in fruits.enumerated() {
print("\(index): \(fruit)")
}
2. while + 下标
var i = 0
while i < fruits.count {
print(fruits[i])
i += 1
}
七、函数式方法(推荐!)
| 方法 | 功能 | 示例 |
|---|---|---|
map | 转换 | numbers.map { $0 * 2 } |
filter | 过滤 | numbers.filter { $0 > 10 } |
reduce | 聚合 | numbers.reduce(0, +) |
sorted | 排序 | numbers.sorted() |
contains | 包含 | fruits.contains("苹果") |
let scores = [95, 88, 70, 82]
// 转换为等级
let grades = scores.map { $0 >= 60 ? "及格" : "不及格" }
// 筛选高分
let high = scores.filter { $0 >= 90 }
// 总分
let total = scores.reduce(0, +)
// 排序
let sorted = scores.sorted(by: >) // 降序
八、数组比较
[1, 2, 3] == [1, 2, 3] // true(内容相等)
[1, 2] < [1, 2, 3] // true(逐元素比较)
值类型:
==比较内容,不是引用
九、安全下标扩展
extension Collection {
subscript(safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
// 使用
fruits[safe: 10] // nil(不崩溃)
十、数组切片(ArraySlice)
let slice = fruits[1..<3] // ArraySlice<String>
let array = Array(slice) // 转回 [String]
注意:
ArraySlice共享原数组内存,适合临时使用
十一、多维数组
let matrix: [[Int]] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(matrix[1][2]) // 6
十二、性能优化
| 场景 | 推荐做法 |
|---|---|
| 频繁添加 | reserveCapacity(n) |
| 大数组遍历 | for-in |
| 转换过滤 | map + filter 链 |
| 去重 | Set(array) |
var bigArray = [Int]()
bigArray.reserveCapacity(100_000) // 预分配
十三、数组去重
// 方式1:Set
let unique = Array(Set(dirtyArray))
// 方式2:reduce + 字典
func unique<T: Hashable>(_ array: [T]) -> [T] {
var seen = Set<T>()
return array.filter { seen.insert($0).inserted }
}
十四、实战项目:Todo List 核心
struct TodoItem {
let id = UUID()
var title: String
var isCompleted = false
}
class TodoList {
private var items: [TodoItem] = []
func add(_ title: String) {
items.append(TodoItem(title: title))
}
func toggle(at index: Int) {
guard index < items.count else { return }
items[index].isCompleted.toggle()
}
func completed() -> [TodoItem] {
return items.filter { $0.isCompleted }
}
func pending() -> [TodoItem] {
return items.filter { !$0.isCompleted }
}
func printAll() {
items.enumerated().forEach { i, item in
let status = item.isCompleted ? "Completed" : "Pending"
print("\(i). [\(status)] \(item.title)")
}
}
}
// 使用
let todo = TodoList()
todo.add("学习 Swift")
todo.add("写代码")
todo.toggle(at: 0)
todo.printAll()
十五、数组速查表
| 操作 | 代码 |
|---|---|
| 创建 | [1,2,3] |
| 添加 | append, += |
| 删除 | remove(at:), removeLast() |
| 长度 | .count |
| 判空 | .isEmpty |
| 第一个 | .first |
| 遍历 | for-in, enumerated() |
| 转换 | .map { } |
| 过滤 | .filter { } |
| 聚合 | .reduce(0, +) |
| 排序 | .sorted() |
| 包含 | .contains() |
| 去重 | Array(Set()) |
十六、练习题(当场写!)
// 1. 实现数组倒序(不使用 reversed())
func reverse<T>(_ array: [T]) -> [T] {
// 你的代码
}
// 2. 找出数组中出现次数最多的元素
func mostFrequent<T: Hashable>(_ array: [T]) -> T? {
// 你的代码
}
// 3. 实现 flatten:[[1,2],[3,4]] → [1,2,3,4]
func flatten<T>(_ array: [[T]]) -> [T] {
// 你的代码
}
答案(展开查看)
点击查看答案
// 1.
func reverse<T>(_ array: [T]) -> [T] {
var result = [T]()
result.reserveCapacity(array.count)
for i in array.indices.reversed() {
result.append(array[i])
}
return result
}
// 2.
func mostFrequent<T: Hashable>(_ array: [T]) -> T? {
let freq = array.reduce(into: [:]) { $0[$1, default: 0] += 1 }
return freq.max(by: { $0.value < $1.value })?.key
}
// 3.
func flatten<T>(_ array: [[T]]) -> [T] {
return array.reduce([]) { $0 + $1 }
}
总结:数组黄金法则
| 法则 | 说明 |
|---|---|
1. 优先用 [T] 字面量 | 简洁 |
| 2. 能用函数式就不用循环 | map/filter/reduce |
3. 大数组用 reserveCapacity | 性能 |
4. 安全访问用 first / safe 下标 | 防崩溃 |
5. 去重用 Set | 高效 |
6. 切片用 Array(slice) 转回数组 | 避免内存泄漏 |
你已完全掌握 Swift 数组!
回复关键词继续学习:
Swift 数组性能优化Swift 函数式编程实战Swift 泛型数组SwiftUI List 与数组绑定
现在就用 map + filter + reduce 一行算出 [1,2,3,4,5] 中偶数的平方和!