Swift
提供了三种主要的集合类型,所谓的数组、合集还有字典,用来储存值的集合。数组是有序的值的集合。合集是唯一值的无序集合。字典是无序的键值对集合。
Swift
中的数组、合集和字典总是明确能储存的值的类型以及它们能储存的键。就是说你不会意外地插入一个错误类型的值到集合中去。它同样意味着你可以从集合当中取回确定类型的值。
Swift
的数组、合集和字典是以泛型集合实现的。
集合的可变性
如果你创建一个数组、合集或者一个字典,并且赋值给一个变量,那么创建的集合就是可变的。这意味着你随后可以通过添加、移除、或者改变集合中的元素来改变(或者说异变)集合。如果你把数组、合集或者字典赋值给一个常量,则集合就成了不可变的,它的大小和内容都不能被改变。
集合不需要改变的情况下创建不可变集合是个不错的选择。这样做可以允许 Swift 编译器优化你创建的集合的性能。
数组
数组以有序的方式来储存相同类型的值。相同类型的值可以在数组的不同地方多次出现。
Swift
的Array
类型被桥接到了基础框架的NSArray
类上。
数组类型简写语法
Swift
数组的类型完整写法是Array<Element>
, Element
是数组允许存入的值的类型。你同样可以简写数组的类型为 [Element]
。尽管两种格式功能上相同,我们更推荐简写并且涉及到数组类型的时候都会使用简写。
创建一个空数组
|
|
注意 someInts
变量的类型通过初始化器的类型推断为 [Int]
。
相反,如果内容已经提供了类型信息, 比如说作为函数的实际参数或者已经分类了的变量或常量,你可以通过空数组字面量来创建一个空数组,它写作[ ]
(一对空方括号) :
|
|
使用默认值创建数组
Swift
的 Array
类型提供了初始化器来创建确定大小且元素都设定为相同默认值的数组。你可以传给初始化器对应类型的默认值(叫做 repeating
)和新数组元素的数量(叫做 count
):
|
|
通过连接两个数组来创建数组
你可以通过把两个兼容类型的现存数组用加运算符(+)
加在一起来创建一个新数组。新数组的类型将从你相加的数组里推断出来:
|
|
使用数组字面量创建数组
你同样可以使用数组字面量来初始化一个数组,它是一种以数组集合来写一个或者多个值的简写方式。数组字面量写做一系列的值,用逗号分隔,用方括号括起来:
|
|
shoppingList
变量被声明为“字符串值的数组”写做 [String]
。由于这个特定的数组拥有特定的String
值类型,它就只能储存 String
值。这里, shoppingList
被两个 String
值( "Eggs"和 "Milk")
初始化,写在字符串字面量里。
依托于 Swift
的类型推断,如果你用包含相同类型值的数组字面量初始化数组,就不需要写明数组的类型。shoppingList
的初始化可以写得更短:
|
|
因为数组字面量中的值都是相同的类型,Swift 就能够推断 [String]是 shoppingList变量最合适的类型。
访问和修改数组
你可以通过数组的方法和属性来修改数组,或者使用下标脚本语法。要得出数组中元素的数量,检查只读的 count
属性:
|
|
使用布尔量 isEmpty
属性来作为检查 count属性是否等于 0
的快捷方式:
|
|
你可以通过 append(_:)
方法给数组末尾添加新的元素:
|
|
另外,可以使用加赋值运算符 (+=)
来在数组末尾添加一个或者多个同类型元素:
|
|
通过下标脚本语法来从数组当中取回一个值,在紧跟数组名后的方括号内传入你想要取回的值的索引:
|
|
你可以使用下标脚本语法来改变给定索引中已经存在的值:
|
|
你同样可以使用下标脚本语法来一次改变一个范围的值,就算替换与范围长度不同的值的合集也行。下面的栗子替换用 “Bananas”和 “Apples”替换 “Chocolate Spread”, “Cheese”, and “Butter”:
|
|
调用 insert(_:at:)
方法插入了一个新元素值为 "Maple Syrup"
到 shopping list
的最前面,通过明确索引位置为 0 .
类似地,你可以使用remove(at:)
方法来移除一个元素。这个方法移除特定索引的元素并且返回它(尽管你不需要的话可以无视返回的值):
|
|
遍历一个数组
你可以用 for-in
循环来遍历整个数组中值的合集
|
|
如果你需要每个元素以及值的整数索引,使用 enumerated()方法来遍历数组。 enumerated()方法返回数组中每一个元素的元组,包含了这个元素的索引和值。你可以分解元组为临时的常量或者变量作为遍历的一部分:
|
|
合集
合集将同一类型且不重复的值、无序地储存在一个集合当中。当元素的顺序不那么重要的时候你就可以使用合集来代替数组,或者你需要确保元素不会重复的时候。
注意:Swift
的 Set
类型桥接到了基础框架的 NSSet
类上。
Set 类型的哈希值
为了能让类型储存在合集当中,它必须是可哈希的——就是说类型必须提供计算它自身哈希值的方法。哈希值是Int
值且所有的对比起来相等的对象都相同,比如 a == b
,它遵循 a.hashValue == b.hashValue。
所有 Swift
的基础类型(比如 String, Int, Double
, 和 Bool
)默认都是可哈希的,并且可以用于合集或者字典的键。没有关联值的枚举成员值(如同枚举当中描述的那样)同样默认可哈希。
你可以使用你自己自定义的类型作为合集的值类型或者字典的键类型,只要让它们遵循 Swift 基础库的 Hashable协议即可。遵循 Hashable协议的类型必须提供可获取的叫做 hashValue的 Int属性。通过 hashValue属性返回的值不需要在同一个程序的不同的执行当中都相同,或者不同程序。
因为 Hashable协议遵循 Equatable,遵循的类型必须同时一个“等于”运算符 ( ==)的实现。 Equatable协议需要任何遵循 ==的实现都具有等价关系。就是说, ==的实现必须满足以下三个条件,其中 a, b, 和 c是任意值:
a == a
(自反性)a == b
意味着b == a
(对称性)a == b && b == c
意味着a == c
(传递性)
合集类型语法
Swift
的合集类型写做 Set<Element>
,这里的 Element
是合集要储存的类型。不同与数组,合集没有等价的简写。
创建并初始化一个空合集
你可以使用初始化器语法来创建一个确定类型的空合集:
|
|
另外,如果内容已经提供了类型信息,比如函数的实际参数或者已经分类的变量常量,你就可以用空的数组字面量来创建一个空合集:
|
|
使用数组字面量创建合集
你同样可以使用数组字面量来初始化一个合集,算是一种写一个或者多个合集值的快捷方式。
|
|
favoriteGenres
变量被声明为“ String
值的合集”,写做 Set<String>
。由于这个合集已经被明确值类型为 String
,它只允许储存 String
值。这时,合集 favoriteGenres
用三个写在数组字面量中的 String
值 ( "Rock", "Classical", 和 "Hip hop")
初始化。
由于 Swift
的类型推断,你不需要在使用包含相同类型值的数组字面量初始化合集的时候写合集的类型。 favoriteGenres
的初始化可以写的更短一些:
|
|
访问和修改合集
Swift
提供一些列API来访问和修改集合:count、isEmpty、insert(_:)、remove(_:)、removeAll()、contains(_:)
遍历合集
你可以在 for-in
循环里遍历合集的值。Swift
的 Set
类型是无序的。要以特定的顺序遍历合集的值,使用 sorted()
方法,它把合集的元素作为使用 <
运算符排序了的数组返回
|
|
执行合集操作
下边的示例描述了两个合集—— a
和 b
——在各种合集操作下的结果,用阴影部分表示。
- 使用
intersection(_:)
方法来创建一个只包含两个合集共有值的新合集; - 使用
symmetricDifference(_:)
方法来创建一个只包含两个合集各自有的非共有值的新合集; - 使用
union(_:)
方法来创建一个包含两个合集所有值的新合集; - 使用
subtracting(_:)
方法来创建一个两个合集当中不包含某个合集值的新合集。
下面的示例描述了三个合集—— a
, b
和 c
——用重叠区域代表合集之间值共享。合集 a
是合集 b
的超集,因为 a
包含 b
的所有元素。相反地,合集 b
是合集 a的
子集,因为 b
的所有元素被 a
包含。合集 b
和合集 c
是不相交的,因为他们的元素没有相同的。
- 使用“相等”运算符
( == )
来判断两个合集是否包含有相同的值; - 使用
isSubset(of:)
方法来确定一个合集的所有值是被某合集包含; - 使用
isSuperset(of:)
方法来确定一个合集是否包含某个合集的所有值; - 使用
isStrictSubset(of:)
或者isStrictSuperset(of:)
方法来确定是个合集是否为某一个合集的子集或者超集,但并不相等; - 使用
isDisjoint(with:)
方法来判断两个合集是否拥有完全不同的值。
|
|
字典
字典储存无序的互相关联的同一类型的键和同一类型的值的集合。每一个值都与唯一的键相关联,它就好像这个值的身份标记一样。不同于数组中的元素,字典中的元素没有特定的顺序。当你需要查找基于特定标记的值的时候使用字典,很类似现实生活中字典用来查找特定字的定义。
字典类型简写语法
Swift
的字典类型写全了是这样的: Dictionary<Key, Value>
,其中的 Key
是用来作为字典键的值类型, Value
就是字典为这些键储存的值的类型。
字典的
Key
类型必须遵循Hashable
协议,就像合集的值类型
简写形式:[Key: Value]
创建一个空字典
就像数组,你可以用初始化器语法来创建一个空 Dictionary
:
|
|
如果内容已经提供了信息,你就可以用字典字面量创建空字典了,它写做 [:](在一对方括号里写一个冒号):
|
|
用字典字面量创建字典
你同样可以使用字典字面量来初始化一个字典,它与数组字面量看起来差不多。字典字面量是写一个或者多个键值对为 Dictionary
集合的快捷方式。
键值对由一个键和一个值组合而成,每个键值对里的键和值用冒号分隔。键值对写做一个列表,用逗号分隔,并且最终用方括号把它们括起来:
[key 1: value 1, key 2: value 2, key 3: value 3]
|
|
与数组一样,如果你用一致类型的字典字面量初始化字典,就不需要写出字典的类型了。 airports
的初始化就能写的更短:
|
|
访问和修改字典
你可以通过字典自身的方法和属性来访问和修改它,或者通过使用下标脚本语法。
如同数组:
- 你可以使用
count
只读属性来找出 Dictionary拥有多少元素
|
|
- 用布尔量
isEmpty
属性作为检查count
属性是否等于0
的快捷方式
|
|
- 你可以用下标脚本给字典添加新元素。使用正确类型的新键作为下标脚本的索引,然后赋值一个正确类型的值
|
|
- 你同样可以使用下标脚本语法来改变特定键关联的值:
|
|
updateValue(_:forKey:)
。不同于下标脚本,updateValue(_:forKey:)
方法在执行更新之后返回旧的值。这允许你检查更新是否成功。
updateValue(_:forKey:)
方法返回一个字典值类型的可选项值。比如对于储存 String
值的字典来说,方法会返回 String?
类型的值,或者说“可选的 String
”。这个可选项包含了键的旧值如果更新前存在的话,否则就是 nil
:
|
|
- 你可以使用下标脚本语法给一个键赋值
nil
来从字典当中移除一个键值对:
|
|
- 另外,使用
removeValue(forKey:)
来从字典里移除键值对。这个方法移除键值对如果他们存在的话,并且返回移除的值,如果值不存在则返回nil
:
|
|
遍历字典
你可以用 for-in
循环来遍历字典的键值对。字典中的每一个元素返回为(key, value)
元组,你可以解开元组成员到临时的常量或者变量作为遍历的一部分:
|
|
你同样可以通过访问字典的 keys
和 values
属性来取回可遍历的字典的键或值的集合:
|
|
如果你需要和接收 Array
实例的 API
一起使用字典的键或值,就用 keys
或 values
属性来初始化一个新数组:
|
|
Swift
的 Dictionary
类型是无序的。要以特定的顺序遍历字典的键或值,使用键或值的 sorted()
方法。
摘自:swift 官网
所有代码在Xcode9 Swift4 环境编译没问题,代码戳这里 https://github.com/keshiim/LearnSwift4