Swift 数组
数组(Array)是 Swift 里最常用的集合类型——有序、可重复、同类型。从保存一组用户列表到处理 API 返回数据,数组几乎无处不在。本章讲透增删改查和高阶函数,顺带提一下 Set。
1. 创建与访问
// 数组:有序、可重复、同类型
var nums: [Int] = [1, 2, 3]
var fruits = ["apple", "banana"] // 类型推断 [String]
var empty1: [Double] = []
var empty2 = [String]()
// 个数、是否空
print(nums.count) // 3
print(nums.isEmpty) // false
// 访问:用 Int 下标(注意越界会崩溃!)
print(nums[0]) // 1
// print(nums[10]) // 运行时崩溃!
// 安全访问:first / last 返回 Optional
print(nums.first ?? -1) // 1
print(nums.last ?? -1) // 3几个关键点:
- 同类型:数组所有元素必须是同一类型,Swift 在编译期检查。
- Int 下标越界会崩溃——Swift 不会自动返回 nil,要么确认长度,要么用
first/last。 - 类型声明用
[T]或Array<T>(前者更常用)。
2. 增删改
// 添加
var arr = [1, 2, 3]
arr.append(4) // 末尾加
arr.insert(0, at: 0) // 指定位置插
arr += [5, 6] // 拼接另一个数组
print(arr) // [0, 1, 2, 3, 4, 5, 6]
// 修改
arr[0] = 100
print(arr) // [100, 1, 2, 3, 4, 5, 6]
// 删除
arr.remove(at: 0) // 删除指定位置,返回被删的值
arr.removeLast() // 删末尾(比 remove(at:) 高效)
arr.removeFirst() // 删开头
arr.removeAll { $0 < 3 } // 条件删除
print(arr)
// 替换一个范围
var nums2 = [1, 2, 3, 4, 5]
nums2[1...3] = [20, 30]
print(nums2) // [1, 20, 30, 5]Swift 数组的方法名都自描述:append / insert / remove / removeLast。注意 removeLast() 比 remove(at: count-1) 高效(O(1) vs O(n))。
3. 遍历
// 遍历
let fruits = ["apple", "banana", "cherry"]
// 只取值
for fruit in fruits {
print(fruit)
}
// 同时取索引和值
for (i, fruit) in fruits.enumerated() {
print("\(i): \(fruit)")
}
// 只要索引
for i in fruits.indices {
print(i, fruits[i])
}
// 切片遍历(等于 fruits[1..<3])
for fruit in fruits[1...2] {
print(fruit) // banana cherry
}三种常用模式:只要值用 for x in arr;要索引和值用 .enumerated();只要索引用 .indices。
4. 高阶函数:map / filter / reduce
这是 Swift 函数式编程的核心三件套。学会它们,你的代码会大幅简化:
let nums = [1, 2, 3, 4, 5]
// map:对每个元素做变换,返回新数组
let squares = nums.map { $0 * $0 }
print(squares) // [1, 4, 9, 16, 25]
// filter:筛选满足条件的元素
let evens = nums.filter { $0 % 2 == 0 }
print(evens) // [2, 4]
// reduce:把所有元素聚合成一个值
let total = nums.reduce(0, +) // 等价 { $0 + $1 }
print(total) // 15
// 链式调用(函数式风格)
let result = nums
.filter { $0 % 2 == 1 } // [1, 3, 5]
.map { $0 * 10 } // [10, 30, 50]
.reduce(0, +) // 90
print(result)
// 类型可以变:整数数组 → 字符串数组
let strs = nums.map { "第 \($0) 个" }
print(strs)- map:对每个元素做变换,返回等长新数组。
- filter:筛选满足条件的元素。
- reduce:聚合所有元素成一个值(求和、求积、拼字符串)。
它们可以链式组合,写出几乎像数学公式的代码。$0、$1 是匿名参数名,简短闭包用。
5. 排序、查找
let nums = [3, 1, 4, 1, 5, 9, 2, 6]
// 排序:返回新数组
let asc = nums.sorted() // [1, 1, 2, 3, 4, 5, 6, 9]
let desc = nums.sorted(by: >) // [9, 6, 5, 4, 3, 2, 1, 1]
// 原地排序(需要 var)
var copy = nums
copy.sort()
// 反转
let reversed = nums.reversed() // ReversedCollection
print(Array(reversed))
// 包含、查找
print(nums.contains(5)) // true
print(nums.first(where: { $0 > 4 }) ?? -1) // 5(第一个大于 4 的)
print(nums.last(where: { $0 < 3 }) ?? -1) // 2
// 找索引
print(nums.firstIndex(of: 4) ?? -1) // 2
print(nums.firstIndex(where: { $0 > 5 }) ?? -1) // 5
// 去重(Swift 没有内置 unique,常见模式)
let unique = Array(Set(nums)) // 顺序不保证
let ordered = Array(NSOrderedSet(array: nums)) as! [Int]
print(unique, ordered)注意 sorted()(返回新数组)和 sort()(原地排序,需要 var)的区别。first(where:)、contains 这些查找函数都接受闭包,灵活强大。
6. Set:无序不重复集合
当你需要"去重"或"成员判断"时,Set 比 Array 高效(查找 O(1))。Set 元素必须 Hashable:
// Set:无序、不重复的集合
var primes: Set<Int> = [2, 3, 5, 7]
var mixed: Set = [1, 2, 2, 3, 3, 3]
print(mixed.count) // 3(去重)
// 增删
primes.insert(11)
primes.remove(2)
// 集合运算
let a: Set = [1, 2, 3, 4]
let b: Set = [3, 4, 5, 6]
print(a.intersection(b)) // {3, 4}(交集)
print(a.union(b)) // {1,2,3,4,5,6}(并集)
print(a.subtracting(b)) // {1, 2}(差集)
print(a.symmetricDifference(b)) // {1, 2, 5, 6}(对称差)
// 元素必须 Hashable(可哈希),自定义类型要实现 Hashable 协议Set 支持完整的集合运算:交集、并集、差集、对称差。处理"标签"、"权限"、"类别"这类问题时非常好用。
7. 值类型特性
Swift 的 Array 是 struct(值类型)。赋值或传参时会"复制",但用了写时复制(COW)优化——只有真正修改时才物理拷贝。这点和 NSMutableArray 完全不同:
var a = [1, 2, 3]
var b = a // 复制(逻辑上)
b.append(4) // 这里才物理拷贝
print(a) // [1, 2, 3](a 不受影响)
print(b) // [1, 2, 3, 4]值类型的好处是线程安全、心智负担低——你永远不会遇到"一个地方改了数组,另一个地方莫名其妙变了"的 bug。
8. 性能对比一览
- append / removeLast:O(1),均摊。
- insert(at:) / remove(at:):O(n),因为要移动元素。
- 下标访问:O(1)。
- contains / firstIndex(of:):O(n),线性扫描。
- Set contains:O(1),哈希查找。
性能关键场景:频繁"成员判断"用 Set;频繁"末尾增删"用 Array;频繁"中间插入"考虑链表(标准库没有,需要自己实现)。
小结
数组是 Swift 最常用的集合。核心:增删改查 + map/filter/reduce + 遍历 + Set 去重。掌握这些,日常 80% 的数据处理任务都能搞定。下一篇讲字典——数组的"键值对"兄弟。
← 上一篇 Swift 字符串
下一篇 Swift 字典 →