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

几个关键点:

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)

它们可以链式组合,写出几乎像数学公式的代码。$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. 性能对比一览

性能关键场景:频繁"成员判断"用 Set;频繁"末尾增删"用 Array;频繁"中间插入"考虑链表(标准库没有,需要自己实现)。

小结

数组是 Swift 最常用的集合。核心:增删改查 + map/filter/reduce + 遍历 + Set 去重。掌握这些,日常 80% 的数据处理任务都能搞定。下一篇讲字典——数组的"键值对"兄弟。

← 上一篇 Swift 字符串

下一篇 Swift 字典

✈️💬