Logo
Section 1 / 2

Swift 数组

了解 Swift 数组,以及如何创建、初始化、管理并操作数组。

检查点

Swift 数组

了解 Swift 数组,以及如何创建、初始化、管理并操作数组。

数组和字典是 Swift 中用于存储其他对象集合的容器。在本课中,我们将介绍使用 Swift 数组和字典的一些基础知识。

可变与不可变集合

Swift 中的集合分为可变和不可变两种形式。不可变集合在初始化后其内容无法更改。要创建一个不可变集合,使用 let 关键字将其赋值给常量。相反,如果将集合赋值给变量(使用 var),则该集合是可变的。

Swift 数组初始化

数组是一种专门设计用来在一个有序集合中存储多个值的数据类型。例如,可以创建一个用于存储字符串值列表的数组。严格来说,一个 Swift 数组只能存储相同类型的值。因此,声明为存储字符串的数组不能同时包含整数。不过,也可以创建混合类型的数组,这将在本章稍后展示。数组的类型可以通过类型标注指定,也可以由编译器通过类型推断自动识别。

可以在创建时通过一组值(称为数组字面量)来初始化数组,语法如下:

1var 变量名: [类型] = [值1, 值2, 值3, ……]

以下代码创建了一个赋值给变量的新数组(因此是可变的),并用三个字符串值进行初始化:

1var treeArray = ["Pine", "Oak", "Yew"]

或者,同样的数组也可以通过赋值给常量来创建为不可变的:

1let treeArray = ["Pine", "Oak", "Yew"]

在上述情况下,Swift 编译器会使用类型推断确定数组包含的是 String 类型的值,并防止其他类型值被插入到应用程序的其他位置。

也可以使用类型标注来声明相同的数组:

1var treeArray: [String] = ["Pine", "Oak", "Yew"]

数组在创建时不必立即赋值。以下语法可用于创建一个空数组:

1var 变量名 = [类型]()

例如,以下代码创建了一个用于存储浮点数值的空数组,并将其赋值给名为 priceArray 的变量:

1var priceArray = [Float]()

另一种有用的初始化技术允许数组以指定大小创建,并且每个元素都预先设置为某个默认值:

1var nameArray = [String](repeating: "My String", count: 10)

当编译并执行时,上述代码将创建一个包含 10 个元素的新数组,每个元素初始值均为“My String”。

最后,可以通过将两个现有数组相加(前提是两个数组的元素类型相同)来创建一个新数组。例如:

1let firstArray = ["Red", "Green", "Blue"] 2let secondArray = ["Indigo", "Violet"] 3 4let thirdArray = firstArray + secondArray

在 Swift 中操作数组

一旦数组存在,就可以使用 Swift 提供的大量方法和属性来操作和处理数组内容。以下是部分常用功能:

获取数组元素数量

通过访问数组的 count 属性可以获得数组中项目的数量:

1var treeArray = ["Pine", "Oak", "Yew"] 2var itemCount = treeArray.count 3 4print("项目数量 = \(itemCount)")

判断数组是否为空,可以使用数组的布尔属性 isEmpty:

1var treeArray = [String]() 2 3if treeArray.isEmpty { 4 print("数组为空。") 5} else { 6 print("项目数量 = \(treeArray.count)") 7}

访问数组元素

可以通过索引下标(第一个元素的索引为 0)来访问或修改数组中的特定元素,这种方法称为索引下标访问。以下代码片段输出了数组中索引位置 2 处的字符串值(即 “Yew”):

1var treeArray = ["Pine", "Oak", "Yew"] 2 3print(treeArray[2])

此方法也可用于替换指定索引位置的值:

1var treeArray = ["Pine", "Oak", "Yew"] 2 3print("第1项 = \(treeArray[1])") 4treeArray[1] = "Redwood" 5print("第1项 = \(treeArray[1])")

上述代码将索引位置 1 的当前值替换为 “Redwood”。

遍历数组

遍历数组中最简单的方法是使用 for-in 循环语法。例如,以下代码遍历一个字符串数组的所有元素,并将每个元素输出到控制台:

1let treeArray = ["Pine", "Oak", "Yew", "Maple", "Birch", "Myrtle"] 2 3for tree in treeArray { 4 print(tree) 5}

相同的效果也可以通过调用数组的 forEach() 方法实现。当对数组调用此方法时,它会遍历每个元素并执行指定的代码。例如:

1let treeArray = ["Pine", "Oak", "Yew", "Maple", "Birch", "Myrtle"] 2 3treeArray.forEach { tree in 4 print(tree) 5}

注意,由于每个元素需要执行的任务是以闭包表达式形式定义的,因此可以利用简写参数名进行优化:

1treeArray.forEach { 2 print($0) 3}

随机元素与打乱顺序

调用数组对象的 shuffled() 方法将返回一个随机重新排列顺序的新数组。例如:

1let shuffledTrees = treeArray.shuffled()

要随机访问数组中的一个元素,只需调用 randomElement() 方法:

1let treeArray: [String] = ["Pine", "Oak", "Yew", "Maple", "Birch", "Myrtle"] 2 3print("随机元素 = \(treeArray.randomElement()!)") 4print("随机元素 = \(treeArray.randomElement()!)") 5print("随机元素 = \(treeArray.randomElement()!)")

向数组添加元素

可以使用 append 方法或 + 和 += 运算符向数组添加元素。例如,以下都是向数组添加元素的有效方式:

1var treeArray = ["Pine", "Oak", "Yew"] 2 3treeArray.append("Redwood") 4treeArray += ["Myrtle"] 5treeArray += ["Elm", "Maple", "Birch"] 6 7for tree in treeArray { 8 print(tree) 9}

插入和删除数组元素

可以通过调用数组的 insert(at:) 方法,在指定索引位置插入新元素。插入操作会保留原有所有元素,相当于将它们向右移动以腾出空间:

1var treeArray = ["Pine", "Oak", "Yew"] 2 3treeArray.insert("Maple", at: 0) 4 5for tree in treeArray { 6 print(tree) 7}

类似地,可以通过调用 remove(at:) 方法删除指定索引位置的元素:

1var treeArray = ["Pine", "Oak", "Yew"] 2 3treeArray.remove(at: 2) 4 5for tree in treeArray { 6 print(tree) 7}

要删除数组的最后一个元素,只需调用数组的 removeLast() 方法:

1var treeArray = ["Pine", "Oak", "Yew"] 2 3treeArray.removeLast() 4 5for tree in treeArray { 6 print(tree) 7}

创建混合类型数组

混合类型数组是指可以包含不同类型元素的数组。显然,如果一个数组被声明或推断为 String 类型,则不能再用于存储非字符串类型的对象实例。然而,考虑到 Swift 提供了 Any 类型,情况变得有趣起来。Any 是 Swift 中一种特殊类型,可用于引用任意非特定类类型的对象。因此,声明为包含 Any 类型元素的数组可以存储多种类型的元素。例如,以下代码声明并初始化了一个包含字符串、整数和双精度浮点数元素的混合数组:

1let mixedArray: [Any] = ["A String", 432, 34.989]

使用 Any 类型需谨慎,因为 Any 会隐藏元素的真实类型,使代码容易出现程序员错误。通常需要手动将 Any 数组中的元素转换为正确的类型才能使用。如果对某个元素进行了错误的类型转换,代码可能在编译时不会报错,但在运行时会崩溃。举个例子,考虑以下混合类型数组:

1let mixedArray: [Any] = [1, 2, 45, "Hello"]

假设我们想遍历数组中的整数元素并将它们乘以 10。实现代码可能是这样的:

1let mixedArray: [Any] = ["A String", 432, 34.989] 2 3for object in mixedArray { 4 print(object * 10) 5}

但编译时会触发语法错误,提示无法对 Any 和 Int 类型的操作数进行乘法运算。

1error: cannot convert value of type 'Any' to expected argument type 'Int'

为消除此错误,必须将数组元素向下转型为 Int 类型:

1let mixedArray: [Any] = ["A String", 432, 34.989] 2 3for object in mixedArray { 4 print(object as! Int * 10) 5}

上述代码可以成功编译,但在遇到第一个非整数元素时将导致程序崩溃,报错如下:

1Could not cast value of type 'Swift.String' (0x7fbc071fca58) to 'Swift.Int' (0x7fbc071fe688).

因此,代码必须修改为能够识别每个元素的具体类型。显然,使用 Any 数组在 Swift 中既有优势也有风险。

课程总结

  • 数组在一个有序集合中存储多个值。

  • 赋值给常量的数组是不可变的。

  • 赋值给变量的数组是可变的。

  • 数组可以声明为空,也可以用一组已有元素(称为数组字面量)进行预初始化。

  • 可使用一系列属性和方法获取数组信息,并进行访问、添加、打乱和删除元素。

  • 通过将元素类型设为 Any 可以声明混合类型数组。这是一种应谨慎使用的技巧。

测验

通过测验检验你对 Swift 数组的理解。

练习

通过以下练习巩固你对 Swift 数组的掌握。

练习 1

编写代码,遍历并显示以下数组中的每个元素:

练习

1let myArray = [1, 4, 6, 12, 5, 3, 6]

解答

1let myArray = [1, 4, 6, 12, 5, 3, 6] 2 3for item in myArray { 4 print(item) 5}

练习 2

添加代码,删除以下数组的最后一个元素:

练习

1var myArray = ["Kia", "Ford", "Audi", "Toyota", "BMW", "Tesla"] 2 3for item in myArray { 4 print(item) 5}

解答

1var myArray = ["Kia", "Ford", "Audi", "Toyota", "BMW", "Tesla"] 2 3myArray.removeLast() 4 5for item in myArray { 6 print(item) 7}

练习 3

创建一个包含 20 个元素的数组,每个元素都为数字 10。

练习

1let myArray =

解答

1let myArray = [Int](repeating: 10, count: 20) 2 3for item in myArray { 4 print(item) 5}

Quiz

单选题

给定语句 colorArray[2] 可访问数组中包含字符串 "Red" 的元素,以下哪个语句将该元素赋值给常量 redColor?

1 / 3

Swift 属性包装器

Swift 字典集合