集合类型
使用数组、集合和字典来组织数据。Swift 提供了三种主要的集合类型:数组、集合和字典,用于存储值的集合。数组是有序的值集合。集合是无序的唯一值集合。字典是无序的键值对集合。
Swift 中的数组、集合和字典始终清晰地指明它们可以存储的值和键的类型。这意味着你无法错误地将不合类型的值插入集合中。这也意味着你可以对从集合中检索到的值的类型充满信心。
注意
Swift 的数组、集合和字典类型是作为通用集合实现的。有关通用类型和集合的更多信息,请参见通用类型。
集合的可变性
如果你创建一个数组、集合或字典,并将其赋值给一个变量,则创建的集合将是可变的。这意味着在创建后你可以通过添加、删除或更改集合中的项目来更改(或修改)该集合。如果将数组、集合或字典赋值给常量,则该集合是不可变的,其大小和内容不能更改。
注意
在所有不需要更改集合的情况下创建不可变集合是一个良好的实践。这样可以使你更容易理解代码,并使 Swift 编译器能够优化你创建的集合的性能。
数组
数组将相同类型的值存储在有序列表中。相同的值可以在数组中多次出现在不同的位置。
注意
Swift 的 Array 类型与 Foundation 的 NSArray 类桥接。
有关在 Foundation 和 Cocoa 中使用 Array 的更多信息,请参见 Array 和 NSArray 的桥接。
数组类型简写语法
Swift 数组的类型完全写作 Array<Element>
,其中 Element
是数组允许存储的值的类型。你还可以将数组的类型简写为 [Element]
。尽管这两种形式在功能上是相同的,但简写形式是首选的,并且在本指南中引用数组类型时使用简写形式。
创建空数组
你可以使用初始化器语法创建特定类型的空数组:
swift
复制代码
var someInts: [Int] = []
print("someInts is of type [Int] with \(someInts.count) items.")
// 打印 "someInts is of type [Int] with 0 items."
注意,someInts
变量的类型从初始化器的类型推断为 [Int]
。
或者,如果上下文已经提供了类型信息,例如函数参数或已经有类型的变量或常量,你可以用空数组字面量(即 []
)创建一个空数组:
swift
复制代码
someInts.append(3)
// someInts 现在包含 1 个类型为 Int 的值
someInts = []
// someInts 现在是一个空数组,但仍然是类型 [Int]
创建带有默认值的数组
Swift 的 Array 类型还提供了一个初始化器,用于创建指定大小的数组,并将所有值设置为相同的默认值。你将适当类型的默认值(称为 repeating
)和该值在新数组中重复的次数(称为 count
)传递给此初始化器:
swift
复制代码
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles 的类型为 [Double],等于 [0.0, 0.0, 0.0]
通过将两个数组相加来创建数组
你可以通过使用加法运算符(+
)将两个兼容类型的现有数组相加来创建一个新数组。新数组的类型是从你相加的两个数组的类型推断出来的:
swift
复制代码
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles 的类型为 [Double],等于 [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles 被推断为 [Double],等于 [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
使用数组字面量创建数组
你也可以使用数组字面量初始化数组,这是将一个或多个值写为数组集合的简写方式。数组字面量写作一系列值,使用逗号分隔,并被一对方括号包围:
swift
复制代码
[<#value 1#>, <#value 2#>, <#value 3#>]
下面的示例创建了一个名为 shoppingList
的数组来存储字符串值:
swift
复制代码
var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList 已初始化为两个初始项
shoppingList
变量被声明为“一个字符串值数组”,写作 [String]
。因为这个特定数组指定了值的类型为 String
,所以它只允许存储字符串值。在这里,shoppingList
数组使用两个字符串值("Eggs" 和 "Milk")初始化,并写在数组字面量中。
注意
shoppingList
数组被声明为一个变量(使用 var
引导词),而不是常量(使用 let
引导词),因为在下面的示例中会向购物清单中添加更多项目。
在这个情况下,数组字面量只包含两个字符串值,没有其他内容。这与 shoppingList
变量的声明类型(一个只能包含字符串值的数组)相匹配,因此将数组字面量赋值给 shoppingList
是被允许的,以初始化 shoppingList
的两个初始项。
得益于 Swift 的类型推断,如果你使用一个包含相同类型值的数组字面量来初始化数组,则不必写出数组的类型。shoppingList
的初始化可以写得更短:
swift
复制代码
var shoppingList = ["Eggs", "Milk"]
因为数组字面量中的所有值都是相同类型,Swift 可以推断出 [String]
是 shoppingList
变量的正确类型。
访问和修改数组
你可以通过其方法和属性,或者使用下标语法访问和修改数组。
要找出数组中的项数,可以检查其只读的 count
属性:
swift
复制代码
print("The shopping list contains \(shoppingList.count) items.")
// 打印 "The shopping list contains 2 items."
使用布尔值的 isEmpty
属性作为检查 count
属性是否等于 0 的快捷方式:
swift
复制代码
if shoppingList.isEmpty {
print("The shopping list is empty.")
} else {
print("The shopping list isn't empty.")
}
// 打印 "The shopping list isn't empty."
你可以通过调用数组的 append(_:)
方法向数组的末尾添加新项:
swift
复制代码
shoppingList.append("Flour")
// shoppingList 现在包含 3 项,有人正在做煎饼
或者使用加法赋值运算符(+=
)附加一个或多个兼容项的数组:
swift
复制代码
shoppingList += ["Baking Powder"]
// shoppingList 现在包含 4 项
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList 现在包含 7 项
使用下标语法检索数组中的值,传递你想检索的值的索引,立即在数组名称后面的方括号中:
swift
复制代码
var firstItem = shoppingList[0]
// firstItem 等于 "Eggs"
注意
数组中的第一个项的索引为 0,而不是 1。Swift 中的数组总是以零为索引。
你可以使用下标语法更改给定索引处的现有值:
swift
复制代码
shoppingList[0] = "Six eggs" // 列表中的第一个项现在等于 "Six eggs",而不是 "Eggs"
当你使用下标语法时,指定的索引需要是有效的。例如,尝试写 shoppingList[shoppingList.count] = "Salt"
以尝试将项追加到数组末尾会导致运行时错误。
你还可以使用下标语法一次更改一系列值,即使替换的值集合的长度与要替换的范围不同。以下示例用 "Bananas" 和 "Apples" 替换 "Chocolate Spread"、"Cheese" 和 "Butter":
swift
复制代码
shoppingList[4...6] = ["Bananas", "Apples"]
// shoppingList 现在包含 6 项
要在指定索引处插入项,请调用数组的 insert(_:at:)
方法:
swift
复制代码
shoppingList.insert("Maple Syrup", at: 0)
// shoppingList 现在包含 7 项
// "Maple Syrup" 现在是列表中的第一项
此调用 insert(_:at:)
方法在购物清单的最前面插入一个值为 "Maple Syrup" 的新项,索引为 0。
同样,你可以使用 remove(at:)
方法从数组中删除项。此方法删除指定索引处的项,并返回该项的值:
swift
复制代码
let removedItem = shoppingList.remove(at: 0)
// removedItem 等于 "Maple Syrup"
// shoppingList 现在包含 6 项,"Maple Syrup" 已被移除
你还可以使用 removeLast()
方法从数组末尾删除最后一个项:
swift
复制代码
let lastItem = shoppingList.removeLast()
// lastItem 等于 "Apples"
// shoppingList 现在包含 5 项
遍历数组
可以使用 for
循环来遍历数组中的每个项。Swift 的 for-in
循环可以用来遍历数组中的每个项:
swift
复制代码
for item in shoppingList {
print(item)
}
// 打印 "Six eggs"
// 打印 "Flour"
// 打印 "Baking Powder"
// 打印 "Bananas"
// 打印 "Cheese"
如果你还想获得每个项的索引,可以使用 enumerated()
方法与 for-in
循环一起使用:
swift
复制代码
for (index, item) in shoppingList.enumerated() {
print("Item \(index + 1): \(item)")
}
// 打印 "Item 1: Six eggs"
// 打印 "Item 2: Flour"
// 打印 "Item 3: Baking Powder"
// 打印 "Item 4: Bananas"
// 打印 "Item 5: Cheese"
集合
集合是一种无序的、唯一的值集合。集合中的值不能重复,这使得它们在需要确保值唯一的情况中非常有用。集合中的值可以是任何 Hashable 类型的值(例如字符串、数字或自定义结构体)。有关 Hashable 的更多信息,请参见集合。
注意
Swift 的 Set 类型与 Foundation 的 NSSet 类桥接。
集合类型简写语法
Swift 中的集合类型完全写作 Set<Element>
,其中 Element
是集合允许存储的值的类型。可以将集合类型简写为 Set<Element>
。
创建空集合
可以使用初始化器语法创建特定类型的空集合:
swift
复制代码
var letters = Set<Character>()
print("letters 是一个空的 Set<Character>,包含 \(letters.count) 项")
// 打印 "letters 是一个空的 Set<Character>,包含 0 项"
你也可以用集合字面量创建一个特定类型的集合。例如,下面的示例创建一个字符的集合:
swift
复制代码
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 的类型为 Set<String>
你也可以使用字面量创建一个包含数字的集合:
swift
复制代码
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 的类型为 Set<String>
集合操作
可以使用多个方法和属性来操作集合,包括获取元素的数量、添加和删除元素等。与数组类似,集合也有一个只读属性 count
,可以找到集合中项的数量:
swift
复制代码
print("I have \(favoriteGenres.count) favorite music genres.")
// 打印 "I have 3 favorite music genres."
你可以使用 insert(_:)
方法向集合中添加新项:
swift
复制代码
favoriteGenres.insert("Jazz")
// favoriteGenres 现在包含 4 项
要从集合中删除项,可以使用 remove(_:)
方法:
swift
复制代码
if let removedGenre = favoriteGenres.remove("Rock") {
print("\(removedGenre) 已从集合中移除。")
} else {
print("集合中没有 Rock。")
}
// 打印 "Rock 已从集合中移除。"
要检查集合中是否包含某个项,可以使用 contains(_:)
方法:
swift
复制代码
if favoriteGenres.contains("Funk") {
print("我喜欢 Funk。")
} else {
print("我不喜欢 Funk。")
}
// 打印 "我不喜欢 Funk。"
遍历集合
与数组一样,可以使用 for-in
循环遍历集合中的每个项。尽管集合是无序的,但每次遍历的结果都可以相同:
swift
复制代码
for genre in favoriteGenres {
print(genre)
}
// 结果无序,可能打印 "Classical"、"Hip hop"、"Jazz"
字典
字典是无序的键值对集合。字典中的每个值都通过其唯一的键进行访问。字典的键是唯一的,不能重复。
注意
Swift 的 Dictionary 类型与 Foundation 的 NSDictionary 类桥接。
字典类型简写语法
Swift 中的字典类型完全写作 Dictionary<Key, Value>
,其中 Key
是字典中键的类型,Value
是字典中值的类型。你可以将字典的类型简写为 [Key: Value]
。
创建空字典
可以使用初始化器语法创建特定类型的空字典:
swift
复制代码
var namesOfIntegers = [Int: String]()
print("namesOfIntegers 是一个空的 [Int: String] 字典,包含 \(namesOfIntegers.count) 项")
// 打印 "namesOfIntegers 是一个空的 [Int: String] 字典,包含 0 项"
创建字典
可以使用字典字面量创建字典。例如,下面的示例创建一个包含整数及其名称的字典:
swift
复制代码
var namesOfIntegers = [0: "零", 1: "一", 2: "二"]
注意
Swift 会自动推断字典的类型为 [Int: String]
,因为字典字面量中的键是整数,而值是字符串。
访问和修改字典
与数组和集合一样,可以使用多种方法和属性访问和修改字典。可以使用字典的只读属性 count
查找字典中项的数量:
swift
复制代码
print("namesOfIntegers 现在包含 \(namesOfIntegers.count) 项")
// 打印 "namesOfIntegers 现在包含 3 项"
要访问字典中的值,可以使用下标语法,传入要访问的键的值:
swift
复制代码
let numberName = namesOfIntegers[2]
// numberName 等于 "二"
如果你访问的键在字典中不存在,结果将是 nil
。可以使用可选绑定语法检查:
swift
复制代码
if let numberName = namesOfIntegers[5] {
print("数字 5 的名称是 \(numberName)")
} else {
print("数字 5 不在字典中。")
}
// 打印 "数字 5 不在字典中。"
要添加或更改字典中的值,可以使用下标语法:
swift
复制代码
namesOfIntegers[1] = "壹"
// namesOfIntegers[1] 现在等于 "壹"
namesOfIntegers[4] = "四"
// namesOfIntegers 现在包含 4 项,包括键 4 的新项
要删除字典中的项,可以使用 removeValue(forKey:)
方法:
swift
复制代码
let oldValue = namesOfIntegers.removeValue(forKey: 2)
// oldValue 等于 "二"
// namesOfIntegers 现在只包含 3 项
遍历字典
与其他集合类型相同,可以使用 for-in
循环遍历字典中的每个键值对:
swift
复制代码
for (number, name) in namesOfIntegers {
print("\(number): \(name)")
}
// 打印:
// 0: 零
// 1: 壹
// 4: 四
如果你想要以特定顺序访问字典的键,可以使用 keys
属性和排序方法:
swift
复制代码
for number in namesOfIntegers.keys.sorted() {
print("\(number): \(namesOfIntegers[number]!)")
}
// 打印:
// 0: 零
// 1: 壹
// 4: 四