Swift 数组(手把手讲解)

Swift 数组:初学者的实用指南

在 Swift 编程语言中,Swift 数组 是最基础也是最常用的数据结构之一。你可以把它想象成一个“购物清单”——你把需要买的东西按顺序列出来,每样东西都有自己的位置,随时可以查看、添加或删除。Swift 数组正是这样一种有序集合,它能存储多个相同类型的值,非常适合处理列表类数据。

对于初学者来说,掌握 Swift 数组 的基本操作是迈向高效编程的第一步。而对中级开发者而言,理解其底层机制和高级用法,能让你在写代码时更优雅、更安全。这篇文章将带你从零开始,系统地掌握 Swift 数组 的核心知识,包括创建、增删改查、遍历、性能优化以及常见陷阱。


创建数组与初始化

在 Swift 中,创建数组非常直观。你可以使用数组字面量语法,用方括号 [ ] 包裹一组值,并用逗号分隔。

// 创建一个存储整数的数组
let numbers = [1, 2, 3, 4, 5]

// 创建一个存储字符串的数组
let fruits = ["苹果", "香蕉", "橙子"]

// 创建一个空数组(需要指定类型)
var emptyArray: [String] = []

注释说明

  • let 声明的是不可变数组,值不能修改;
  • var 声明的是可变数组,支持增删改;
  • emptyArray: [String] 显式声明类型,避免编译器推断错误;
  • 如果不指定类型,Swift 会自动推断,但建议在复杂场景下显式声明,提高代码可读性。

Swift 数组是类型安全的,这意味着你不能向一个存储整数的数组中插入字符串。这就像你不能把“牛奶”放进“水果”购物篮一样,编译器会直接报错,防止运行时出错。


基础操作:增、删、改、查

添加元素

向数组添加元素有多种方式,最常用的是 append() 方法。

var colors = ["红色", "蓝色"]
colors.append("绿色")  // 添加一个元素
print(colors)  // 输出: ["红色", "蓝色", "绿色"]

注释说明

  • append() 在数组末尾添加单个元素;
  • 如果你需要添加多个元素,可以用 += 操作符:
colors += ["黄色", "紫色"]  // 批量添加
print(colors)  // 输出: ["红色", "蓝色", "绿色", "黄色", "紫色"]

删除元素

删除元素也有多种方式,比如 removeLast() 删除最后一个,remove(at:) 删除指定索引的元素。

var animals = ["猫", "狗", "兔子", "鸟"]

animals.removeLast()  // 删除最后一个,返回被删除的值
print(animals)  // 输出: ["猫", "狗", "兔子"]

let removed = animals.remove(at: 1)  // 删除索引为 1 的元素(狗)
print("删除的动物是:\(removed)")  // 输出: 删除的动物是:狗

注释说明

  • remove(at:) 返回被删除的元素,可用于后续处理;
  • 如果索引越界,程序会崩溃,因此使用前建议检查索引合法性。

修改元素

修改数组中的元素,直接通过索引赋值即可。

var scores = [85, 90, 78]

scores[1] = 95  // 把第二项改为 95
print(scores)  // 输出: [85, 95, 78]

注释说明

  • 索引从 0 开始,scores[0] 是第一个元素;
  • 如果索引超出范围,编译器会报错,避免非法访问。

查找元素

查找元素可以使用 contains() 方法,判断数组是否包含某个值。

let cities = ["北京", "上海", "广州", "深圳"]

if cities.contains("杭州") {
    print("杭州在列表中")
} else {
    print("杭州不在列表中")  // 输出:杭州不在列表中
}

注释说明

  • contains() 是 O(n) 时间复杂度,适合小数组;
  • 如果你有大量数据,建议使用 Set 提高性能。

遍历数组:for-in 循环与高阶函数

遍历数组是日常开发中高频操作。Swift 提供了多种方式,最常用的是 for-in 循环。

let temperatures = [20, 22, 18, 25, 23]

// 遍历并打印每个温度值
for temp in temperatures {
    print("当前温度:\(temp)°C")
}

注释说明

  • for-in 循环简洁高效,自动处理索引;
  • 如果你需要同时获取索引和值,可以使用 enumerated() 方法。
for (index, temp) in temperatures.enumerated() {
    print("第 \(index + 1) 个温度是:\(temp)°C")
}

注释说明

  • enumerated() 返回 (index, value) 元组;
  • index + 1 是为了从 1 开始计数,更符合人类习惯。

除了基础循环,Swift 还提供了强大的高阶函数,让代码更函数式、更简洁。

let numbers = [1, 2, 3, 4, 5]

// map:对每个元素执行操作并返回新数组
let doubled = numbers.map { $0 * 2 }
print(doubled)  // 输出: [2, 4, 6, 8, 10]

// filter:筛选满足条件的元素
let evenNumbers = numbers.filter { $0 % 2 == 0 }
print(evenNumbers)  // 输出: [2, 4]

// reduce:将数组归约为一个值
let sum = numbers.reduce(0) { $0 + $1 }
print(sum)  // 输出: 15

注释说明

  • map 用于转换;
  • filter 用于筛选;
  • reduce 用于聚合;
  • 这些函数都不修改原数组,返回新数组,符合函数式编程原则。

数组的性能与内存管理

Swift 数组在内部使用连续内存块存储数据,这意味着访问元素非常快,时间复杂度为 O(1)。但这也带来了一些限制:

  • 插入和删除操作在中间位置代价高,因为需要移动后续元素;
  • 数组大小变化频繁时,频繁的内存重分配可能影响性能。

避免频繁修改

如果你需要频繁插入或删除元素,考虑使用 Array 的替代方案:

  • ContiguousArray:性能接近原生数组,但更适用于高性能场景;
  • MutableCollection 协议:用于自定义集合类型。
// 示例:频繁插入时使用数组拼接
var list = [1, 2, 3]

// ❌ 不推荐:在循环中频繁插入
for i in 4...10 {
    list.insert(i, at: 0)  // 每次插入都移动所有元素
}

// ✅ 推荐:先构建,再反转
var temp = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
list = temp + list  // 拼接效率更高

注释说明

  • insert(at:) 在开头插入是 O(n);
  • 拼接操作 + 在某些情况下更高效,尤其当数据量大时。

常见陷阱与最佳实践

1. 索引越界问题

let names = ["Alice", "Bob"]

// ❌ 错误:索引 5 超出范围
// names[5]  // 编译器报错!

最佳实践

  • 使用 indices 检查合法性:
    if 5 < names.count {
        print(names[5])
    }
    

2. 可变性误用

let users = ["张三", "李四"]

// ❌ 试图修改不可变数组
// users.append("王五")  // 编译错误!

最佳实践

  • 明确使用 var 用于可变数组;
  • 使用 let 保护数据不被意外修改。

3. 类型推断不明确

let items = []  // ❌ 编译错误!类型无法推断

最佳实践

  • 显式声明类型:
    var items: [String] = []
    

结语

Swift 数组 是你开发中不可或缺的工具,它既简单又强大。从创建到遍历,从增删改查到性能优化,掌握这些技巧能让你的代码更健壮、更高效。

无论是处理用户列表、商品数据,还是构建游戏中的角色队列,Swift 数组 都能胜任。记住:代码不是写给机器看的,而是写给人看的。清晰的命名、合理的结构、恰当的注释,才能让团队协作更顺畅。

继续深入学习 Swift 的集合类型(如 Set 和 Dictionary),你会发现更多优雅的编程方式。但别忘了,一切从数组开始——它是通往 Swift 高级编程的第一站。