简介
Swift 提供了三种主要的集合类型, 即数组、集合和字典, 用于存储值的集合。
数组是值的有序集合。 集合是唯一值的无序集合。 字典是键值关联的无序集合。
Swift 中的数组、集合和字典总是明确它们可以存储的值和键的类型。这意味着无法在集合中插入错误类型的值, 也意味着可以确定从集合中检索的值的类型。
集合可变性
如果创建一个数组、集合或字典, 将其赋值给一个变量, 那么创建的集合将是可变的。 这意味着在创建集合后,可以通过添加、删除或更改集合中的项目来更改(或突变)集合。
如果将数组、集合或字典赋值给常量,则该集合是不可变的,其大小和内容都无法更改。
如果明确不需要更改集合, 最好的做法就是创建不可变集合。 这样做的好处是让编译器优化集合性能。
数组
数组以有序列表的形式存储相同类型的值。同一个值可以多次出现在数组的不同位置。
创建空数组
// 使用初始化语法创建特定类型的空数组
// 变量名后面加:[数据类型] = []
// []就是空数组的字面量
var ages: [Int] = []
print(ages) // []
创建有默认值的数组
数组类型有 Array
初始化器, 用于创建具有一定大小的数组, 并且将所有值设置为相同的默认值。
// Array初始化器, repeating后面就是默认值, count后面数字表示有几个值。
var ages = Array(repeating: 18, count: 5)
print(ages) // [18, 18, 18, 18, 18]
将已有数组相加创建新数组
使用加法运算符 +
可以将两个类型兼容的数组相加, 创建一个新数组。
let someNames = Array(repeating: "hzclog", count: 3)
print(someNames) // ["hzclog", "hzclog", "hzclog"]
let anotherNames = Array(repeating: "swift", count: 5)
print(anotherNames) // ["swift", "swift", "swift", "swift", "swift"]
let totalNames = someNames + anotherNames
print(totalNames) // ["hzclog", "hzclog", "hzclog", "swift", "swift", "swift", "swift", "swift"]
使用数组字面量创建数组
这是一种将一个或多个值写成数组集合的速记方法。
数组字面形式是一个值列表, 用 ,
分隔, 周围使用方括号包围。
// 初始化时,数组方括号中直接写入值,每个值之间的,不要忘记
let names: [String] = ["陶喆", "王力宏", "周杰伦"]
print(names) // ["陶喆", "王力宏", "周杰伦"]
// 得益于swift类型推断,我们一般去掉类型也可以
let anotherNames = ["林俊杰", "方大同"]
print(anotherNames) // ["林俊杰", "方大同"]
访问和修改数组
count
属性获取数组里面值的数量。
let names: [String] = ["陶喆", "王力宏", "周杰伦"]
print(names.count) // 3
isEmpty
属性获取数组是否为空的布尔值。
let names: [String] = ["陶喆", "王力宏", "周杰伦"]
print(names.isEmpty) // false
append
方法在数组的末尾追加新的元素。
var products = ["apple", "banana"]
print(products) // ["apple", "banana"]
products.append("pear")
print(products) // ["apple", "banana", "pear"]
+=
运算符也可以用于追加一个或多个类型兼容的数组
var products = ["apple", "banana"]
print(products) // ["apple", "banana"]
products += ["pear", "watermelon"]
print(products) // ["apple", "banana", "pear", "watermelon"]
数组[下标]
的方式可以从数组读取指定位置的值。 与字符串索引不同, 使用数字就可以了。
从左到右, 从0开始, 最后一个位置显然就是数组的个数 - 1。
let ages = [18, 22, 20, 19]
print(ages[0]) // 18
print(ages[3]) // 19
给数组指定位置赋值的话,就是更新数组了。
var ages = [18, 22, 20, 19]
print(ages) // [18, 22, 20, 19]
ages[1] = 30
print(ages) // [18, 30, 20, 19]
// 也可以使用范围一次性更改一批
let range = 1...2
// 将位置1和2的元素换成一个110
ages[range] = [110]
print(ages) // [18, 110, 19]
insert(_:at:)
方法可以在指定位置插入元素。
var numbers = [10, 20, 30]
numbers.insert(40, at: 1) // 索引1的位置插入40
print(numbers) // [10, 40, 20, 30]
remove(at:)
方法可以移除并返回指定位置的元素。
var numbers = [10, 20, 30]
let removedItem = numbers.remove(at: 2) // 移除索引2的值
print(numbers) // [10, 20]
print(removedItem) // 30
尝试访问或者修改数组时, 一定要注意索引的边界值。 因为一旦越界, 就会导致运行错误。
removeLast()
方法可以移除并返回数组的最后一项。
var numbers = [10, 20, 30, 40]
let removedItem = numbers.removeLast() // 移除最后一项
print(numbers) // [10, 20, 30]
print(removedItem) // 40
集合
集合将同一类型的不同值, 存储在一个集合中, 没有顺序。
如果值的顺序不重要, 或者要确保每个值只出现一次, 可以使用集合。
可散列值
只有可散列的数据类型, 才可以放在集合中。 即该类型必须提供一种计算散列值的方法。
Swift所有的基本类型(String, Int, Double,Bool)默认都是可散列的。 所以可以直接放在集合中。
如果想使用自定义类型作为集合的值, 必须让它实现Hashable协议。
类型语法
Swift集合类型写法是 Set<Element>
, 其中Element就是集合存储的类型。
创建空集合
使用初始化语法创建空集合。
// 根据初始化器尖括号的类型,numbers变量被推断为Set<Int>
var numbers = Set<Int>()
print(numbers) // []
使用字面量创建集合
可以使用字面量初始化集合,这是一种将值写入集合的快捷方式。
var numbers: Set<Int> = [1, 2, 3]
print(numbers) // [2, 3, 1] 这里顺序不是固定的,可以多次运行看看
// 当然可以简短一点。集合类型声明必须保留,元素类型可以省略
var anotherNumbers: Set = [4, 5, 6]
print(anotherNumbers) // [4, 6, 5] 顺序同样是乱的
访问和修改集合
count
属性获得集合中的元素数量。
let brands: Set = ["apple", "xiaomi", "sunsumg"]
print(brands.count) // 3
isEmpty
属性判断集合是否为空。
let brands: Set = ["apple", "xiaomi", "sunsumg"]
print(brands.isEmpty) // false
insert(_:)
方法插入新的元素。
var brands: Set = ["apple", "xiaomi", "sunsumg"]
brands.insert("huawei")
print(brands) // ["apple", "xiaomi", "huawei", "sunsumg"]
remove(_:)
方法从集合中移除并返回指定元素。
var brands: Set = ["apple", "xiaomi", "sunsumg"]
let removedItem = brands.remove("sunsumg")
print(brands) // ["apple", "xiaomi"]
print(removedItem) // Optional("sunsumg")
contains(_:)
检查集合中是否包含指定元素。
var brands: Set = ["apple", "xiaomi", "sunsumg"]
print(brands.contains("huawei")) // false
集合运算
如果你对数学课程还存有记忆的话, 应该能想起数学中也存在集合的概念。 两个集合可以合并, 可以确定公共值, 可以确定是否包含或者不包含相同的值等等。
Swift中的集合支持这样常见的运算。
交集
intersection(_:)
方法创建一个新集合,返回两个集合都存在的值。
let number1: Set = [1, 2, 3, 4, 5]
let number2: Set = [1, 3, 5, 7, 9]
print(number1.intersection(number2)) // [1, 3, 5]
并集
union(_:)
方法创建一个新集合,包含两个集合所有的值。
let number1: Set = [1, 2, 3, 4, 5]
let number2: Set = [1, 3, 5, 7, 9]
print(number1.union(number2)) // [9, 4, 2, 5, 1, 7, 3]
差集
subtracting(_:)
创建一个新集合,其中的值不在指定集合中。
比如 a.subtracting(b), 就是a集合有, b集合没有的值。
let number1: Set = [1, 2, 3, 4, 5]
let number2: Set = [1, 3, 5, 7, 9]
print(number1.subtracting(number2)) // [4, 2]
print(number2.subtracting(number1)) // [9, 7]
对称差集
symmetricDifference(_:)
创建新集合,里面的值只在其中一个集合中出现过。 相当于 并集 - 交集
。
let number1: Set = [1, 2, 3, 4, 5]
let number2: Set = [1, 3, 5, 7, 9]
print(number1.symmetricDifference(number2)) // [9, 4, 7, 2]
成员与相等关系
相等
==
运算符判断两个集合是否包含所有相同的值。
let number1: Set = [1, 3, 5]
let number2: Set = [1, 5, 3]
print(number1 == number2) // true
子集
isSubset(of:)
方法确定当前集合的值是否都在指定集合中。
let number1: Set = [1, 3, 5]
let number2: Set = [1, 5, 3, 7, 9]
print(number1.isSubset(of: number2)) // true
超集
isSuperset(of:)
方法确定当前集合是否包含指定集合所有的值。
let number1: Set = [1, 3, 5]
let number2: Set = [1, 5, 3, 7, 9]
print(number1.isSuperset(of: number2)) // false
print(number2.isSuperset(of: number1)) // true
严格子集或超集
isStrictSubset(of:)
和 isStrictSuperset(of:)
确定集合是否是指定集合的子集或超集,但不能等于指定集合。
let number1: Set = [1, 3, 5]
let number2: Set = [1, 5, 3, 7, 9]
let number3: Set = [5, 3, 1]
print(number1.isStrictSubset(of: number2)) // true
print(number1.isStrictSubset(of: number3)) // false
print(number2.isStrictSuperset(of: number3)) // true
无共同值
isDisjoint(with:)
方法确定两个集合是否没有共同值。
let number1: Set = [2, 4, 6, 8, 10]
let number2: Set = [1, 5, 3, 7, 9]
let number3: Set = [1, 2, 4, 6]
print(number1.isDisjoint(with: number2)) // true
print(number1.isDisjoint(with: number3)) // false
字典
字典以集合的形式, 存储同一类型的键和同一类型的值之间的关联, 没有顺序。
键就是值在字典中的标识符, 每个值都与一个唯一的键相关联。
速记语法
字典类型写作 Dictionary<Key, Value>
, 其中Key是键的类型, Value是值的类型。
也可以使用速记写法 [Key: Value]
。
字典键的类型必须符合Hashable协议,就像集合的值一样。
创建空字典
使用初始化语法创建特定类型的空字典。
// users是[Int: String]类型的空字典,键是Int,值是String类型
var users: [Int: String] = [:]
print(users) // [:]
使用字面量创建字典
使用字面量初始化字典。 键值对是键和值的组合, 每个键值对中的键和值使用:
分隔, 键值对使用列表的形式书写, 用逗号分隔, 并且使用方括号包围。
var userAges: [String: Int] = ["王力宏": 47, "陶喆": 54, "周杰伦": 46]
print(userAges) // ["陶喆": 54, "王力宏": 47, "周杰伦": 46]
// 字面量形式已经给出了类型,所以可以简短些
var anotherUserAges = ["王力宏": 47, "陶喆": 54, "周杰伦": 46]
print(anotherUserAges) // ["周杰伦": 46, "王力宏": 47, "陶喆": 54]
访问和修改字典
count
属性获得字典键值对的数量。
var productPrice = ["apple": 5.0, "banana": 2.5, "watermelon": 2.0]
print(productPrice.count) // 3
isEmpty
属性返回字典是否为空的布尔值。
var productPrice = ["apple": 5.0, "banana": 2.5, "watermelon": 2.0]
print(productPrice.isEmpty) // false
字典[键]
可以获取字典指定键的值。
var productPrice = ["apple": 5.0, "banana": 2.5, "watermelon": 2.0]
print(productPrice["banana"]) // Optional(2.5)
print(productPrice["pear"]) // nil
字典[键] = 值
语法用于添加或者更新键值对。
var productPrice = ["apple": 5.0, "banana": 2.5, "watermelon": 2.0]
productPrice["pear"] = 1.5
print(productPrice) // ["apple": 5.0, "pear": 1.5, "banana": 2.5, "watermelon": 2.0]
productPrice["apple"] = 7.5
print(productPrice) // ["apple": 7.5, "pear": 1.5, "banana": 2.5, "watermelon": 2.0]
字典[键] = nil
语法用于删除键值对。
var productPrice = ["apple": 5.0, "banana": 2.5, "watermelon": 2.0]
print(productPrice) // ["watermelon": 2.0, "banana": 2.5, "apple": 5.0]
productPrice["apple"] = nil
print(productPrice) // ["banana": 2.5, "watermelon": 2.0]
下一章
通过本篇文章, 我们主要是了解集合类型: 数组、 集合和字典的使用。 掌握这些集合类型的操作非常关键。
下一章中,我们来聊聊Swift中的控制流。