本次的教程是基于Swift5.1版本
Swift 提供了三种主要的集合类型(collection types),所谓的数组(arrays)、集合(sets)还有字典(dictionaries),用来储存值的集合。数组是有序的值的集合。集合是唯一值的无序集合。字典是无序的键值对集合。
集合类型的可变性
如果你创建一个数组、集合或者一个字典,并且赋值给一个变量,那么创建的集合就是可变的。这意味着你随后可以通过添加、移除、或者改变集合中的元素来改变(或者说异变)集合。如果你把数组、集合或者字典赋值给一个常量,则集合就成了不可变的,它的大小和内容都不能被改变。在集合不需要改变的情况下创建不可变集合是个不错的选择。这样做可以允许 Swift 编译器优化你创建的集合的性能。
数组(arrays)
数组以有序的方式来储存相同类型的值。相同类型的值可以在数组的不同地方多次出现。
- 数组类型简写语法
Swift 数组的类型完整写法是 Array< Element >, Element是数组允许存入的值的类型。你同样可以简写数组的类型为 [ Element ]。尽管两种格式功能上相同,我们更推荐简写并且全书涉及到数组类型的时候都会使用简写。
- 创建一个数组
你可以使用确定类型通过初始化器语法来创建一个数组:
代码语言:javascript复制var shoppingList = [String]()
var shoppingList: [String] = ["Eggs", "Milk"]
var shoppingList = ["Eggs", "Milk"]
- 访问和修改数组
你可以通过数组的方法和属性来修改数组,或者使用下标脚本语法。
要得出数组中元素的数量,检查只读的 count属性:
代码语言:javascript复制var intValues = [Int]()
print(intValues.count)
//输出:0
使用布尔量 isEmpty属性来作为检查 count属性是否等于 0的快捷方式:
代码语言:javascript复制var intValues = [Int]()
if intValues.isEmpty{
print("数组是空的")
}else{
print("数组不是空的")
}
//输出:数组是空的
你可以通过 append(_:)方法给数组末尾添加新的元素:
代码语言:javascript复制var intValues = [Int]()
intValues.append(1)
print(intValues)
//输出 [1]
另外,可以使用加赋值运算符 ( =)来在数组末尾添加一个或者多个同类型元素:
代码语言:javascript复制var intValues = [Int]()
intValues =[1]
print(intValues)
//输出 [1]
通过下标脚本语法来从数组当中取回一个值,在紧跟数组名后的方括号内传入你想要取回的值的索引:
代码语言:javascript复制var intValues = [Int]()
intValues =[1]
let a = intValues[0]
print(a)
//输出 1
你可以使用下标脚本语法来改变给定索引中已经存在的值:
代码语言:javascript复制var intValues = [Int]()
intValues =[1]
intValues[0] = 2
print(intValues)
//输出 [2]
要把元素插入到特定的索引位置,调用数组的 insert(_:at:)方法:
代码语言:javascript复制var intValues = [Int]()
intValues.append(1)
intValues.insert(2, at: 1)
print(intValues)
//输出 [1, 2]
你可以使用 remove(at:)方法来移除一个元素。这个方法移除特定索引的元素并且返回它(尽管你不需要的话可以无视返回的值)
代码语言:javascript复制var intValues = [Int]()
intValues.append(1)
intValues.insert(2, at: 1)
let a = intValues.remove(at: 1)
print(a)
//输出2
如果你想要移除数组最后一个元素,使用 removeLast()方法而不是 remove(at:)方法以避免查询数组的 count属性。与 remove(at:)方法相同, removeLast()返回删除了的元素
- 遍历一个数组
你可以用 for-in循环来遍历整个数组中值的集合:
代码语言:javascript复制let names = ["dapeng","dashuai","damei","daqiang"]
for name in names {
print(name)
}
输出
dapeng
dashuai
damei
daqiang
如果你需要每个元素以及值的整数索引,使用 enumerated()方法来遍历数组。enumerated()方法返回数组中每一个元素的元组,包含了这个元素的索引和值。你可以分解元组为临时的常量或者变量作为遍历的一部分:
代码语言:javascript复制let names = ["dapeng","dashuai","damei","daqiang"]
for (index,value) in names.enumerated() {
print("索引:(index) " "值:(value)")
}
输出
索引:0 值:dapeng
索引:1 值:dashuai
索引:2 值:damei
索引:3 值:daqiang
集合(sets)
集和(sets)将同一类型且不重复的值无序地储存在一个集合当中。当元素的顺序不那么重要的时候你就可以使用集合来代替数组,或者你需要确保元素不会重复的时候
- 集合类型语法
Swift 的集合类型写做 Set< Element >,这里的 Element是集合要储存的类型。不同与数组,集合没有等价的简写。
- 创建并初始化一个集合
你可以使用初始化器语法来创建一个确定类型的空集合:
代码语言:javascript复制var stringSet = Set<String>()
var stringSet:Set<String> = ["11","33"]
var stringSet:Set = ["211","985"]
集合类型不能从数组字面量推断出来,所以 Set类型必须被显式地声明。总之,由于 Swift 的类型推断,你不需要在使用包含相同类型值的数组字面量初始化集合的时候写集合的类型。
- 访问和修改集合
你可以通过集合的方法和属性来访问和修改集合。
要得出集合当中元素的数量,检查它的只读 count属性:
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
print(stringSet.count)
//输出 4
使用布尔量 isEmpty属性作为检查 count属性是否等于 0的快捷方式:
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
if stringSet.isEmpty {
print("集合是空")
}else{
print("集合不是空")
}
//输出:集合不是空
你可通过调用 insert(_:)方法来添加一个新的元素到集合:
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
stringSet.insert("55")
你可以通过调用集合的 remove(_:)方法来从集合当中移除一个元素,如果元素是集合的成员就移除它,并且返回移除的值,如果集合没有这个成员就返回 nil。另外,集合当中所有的元素可以用 removeAll()一次移除。
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
stringSet.remove("11")
要检查集合是否包含了特定的元素,使用 contains(_:)方法。
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
if stringSet.contains("11") {
print("包含")
}
//输出:包含
- 遍历集合
你可以在 for-in循环里遍历集合的值。
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
for stringVal in stringSet {
print(stringVal)
}
输出
11
44
33
22
Swift 的 Set类型是无序的。要以特定的顺序遍历集合的值,使用 sorted()方法,它把集合的元素作为使用 < 运算符排序了的数组返回。
代码语言:javascript复制var stringSet:Set = ["11","22","33","44"]
for stringVal in stringSet.sorted() {
print(stringVal)
}
输出
11
22
33
44
- 执行集合操作
你可以高效地执行基本地集合操作,比如合并两个集合,确定两个集合共有哪个值,或者确定两个集合是否包含所有、某些或没有相同的值。
1.使用 intersection(:)方法来创建一个只包含两个集合共有值的新集合; 2.使用 symmetricDifference(:)方法来创建一个只包含两个集合各自有的非共有值的新集合; 3.使用 union(:)方法来创建一个包含两个集合所有值的新集合; 4.使用 subtracting(:)方法来创建一个两个集合当中不包含某个集合值的新集合。
例如:
代码语言:javascript复制var intA:Set = [1,2,3,4]
var intB:Set = [3,4,5,6]
intA.intersection(intB).sorted()
// [3,4]
intA.symmetricDifference(intB).sorted()
// [1,2,5,6]
intA.union(intB).sorted()
// [1,2,3,4,5,6]
intA.subtracting(intB).sorted()
//[1,2]
1.使用“相等”运算符 ( == )来判断两个集合是否包含有相同的值; 2.使用 isSubset(of:) 方法来确定一个集合的所有值是被某集合包含; 3.使用 isSuperset(of:)方法来确定一个集合是否包含某个集合的所有值; 4.使用 isStrictSubset(of:) 或者 isStrictSuperset(of:)方法来确定是个集合是否为某一个集合的子集或者超集,但并不相等; 5.使用 isDisjoint(with:)方法来判断两个集合是否拥有完全不同的值。
例如:
代码语言:javascript复制var intA:Set = [1,2,3,4]
var intB:Set = [3,4,5,6]
var intC:Set = [1,2]
var intD:Set = [8,9]
intA == intB
//false
intC.isSubset(of: intA)
//true
intA.isSuperset(of: intC)
//true
intA.isStrictSuperset(of: intC)
//true
intA.isDisjoint(with: intD)
//true
字典(dictionaries)
字典储存无序的互相关联的同一类型的键和同一类型的值的集合。每一个值都与唯一的键相关联,它就好像这个值的身份标记一样。不同于数组中的元素,字典中的元素没有特定的顺序。当你需要查找基于特定标记的值的时候使用字典,很类似现实生活中字典用来查找特定字的定义。
- 字典类型简写语法
Swift 的字典类型写全了是这样的:Dictionary,其中的 Key是用来作为字典键的值类型, Value就是字典为这些键储存的值的类型。
你同样可以用简写的形式来写字典的类型为 [Key: Value]。尽管两种写法是完全相同的,但本书所有提及字典的地方都会使用简写形式。
- 创建一个字典
var res = [String:String]()
var res:[String:String] = ["name":"dapeng","age":"18"]
var res = ["name":"dapeng","age":"18"]
- 访问和修改字典
你可以通过字典自身的方法和属性来访问和修改它,或者通过使用下标脚本语法。 如同数组,你可以使用 count只读属性来找出 Dictionary拥有多少元素:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
print(res.count)
//输出:2
使用布尔量 isEmpty属性作为检查 count属性是否等于 0的快捷方式:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
if !res.isEmpty {
print("字典不为空")
}
//输出:字典不为空
你可以用下标脚本给字典添加新元素。使用正确类型的新键作为下标脚本的索引,然后赋值一个正确类型的值,或者可以使用下标脚本语法来改变特定键关联的值:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
res["level"] = "高" //添加新值
res["level"] = "非常高" //修改值
作为下标脚本的代替,使用字典的 updateValue( :forKey:)方法来设置或者更新特点键的值。就像上边下标脚本的栗子, updateValue( :forKey:)方法会在键没有值的时候设置一个值,或者在键已经存在的时候更新它。总之,不同于下标脚本, updateValue(_:forKey:)方法在执行更新之后返回旧的值。这允许你检查更新是否成功。
updateValue(_:forKey:)方法返回一个字典值类型的可选项值。比如对于储存 String值的字典来说,方法会返回 String?类型的值,或者说“可选的 String”。这个可选项包含了键的旧值如果更新前存在的话,否则就是 nil:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
if let value = res.updateValue("high", forKey: "age") {
print("旧值:(value)")
}else{
print("这是插入")
}
//输出:旧值:18
你同样可以使用下标脚本语法来从字典的特点键中取回值。由于可能请求的键没有值,字典的下标脚本返回可选的字典值类型。如果字典包含了请求的键的值,下标脚本就返回一个包含这个键的值的可选项。否则,下标脚本返回 nil :
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
if let value = res["age"] {
print(value)
}
//输出:18
你可以使用下标脚本语法给一个键赋值 nil来从字典当中移除一个键值对:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
res["age"] = nil
print(res)
//输出:["name": "dapeng"]
另外,使用 removeValue(forKey:)来从字典里移除键值对。这个方法移除键值对如果他们存在的话,并且返回移除的值,如果值不存在则返回 nil:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
if let val = res.removeValue(forKey: "age") {
print(val)
}
//输出:18
- 遍历字典
你可以用 for-in循环来遍历字典的键值对。字典中的每一个元素返回为 (key, value)元组,你可以解开元组成员到临时的常量或者变量作为遍历的一部分:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
for (key,val) in res {
print("键:(key), 值:(val)")
}
//输出
//键:name, 值:dapeng
//键:age, 值:18
你同样可以通过访问字典的 keys和 values属性来取回可遍历的字典的键或值的集合:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
for key in res.keys {
print(key)
}
for val in res.values {
print(val)
}
如果你需要和接收 Array实例的 API 一起使用字典的键或值,就用 keys或 values属性来初始化一个新数组:
代码语言:javascript复制var res = ["name":"dapeng","age":"18"]
let keys = [String](res.keys)
//["age", "name"]
let vals = [String](res.values)
//["dapeng", "18"]
Swift 的 Dictionary类型是无序的。要以特定的顺序遍历字典的键或值,使用键或值的 sorted()方法。