一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
特征
- 一组无序的元素,每个元素只出现一次
- 通过哈希表实现的,集合中的元素必须满足Hashable
- 遵守ExpressbilByArrayLiteral协议,也就是可以用数组字面量方式初始化一个集合
let naturals: Set = [1, 2, 3, 2]
naturals // [2, 1, 3]
naturals.contains(3) // true
naturals.contains(0) // false
- 与其他类型集合一样,也支持我们那些已经见过的基本操作,如for, map ,filter等
集合代数
补集
let iPods: Set = ["iPod touch", "iPod nano", "iPod mini",
"iPod shuffle", "iPod Classic"]
let discontinuedIPods: Set = ["iPod mini", "iPod Classic",
"iPod nano", "iPod shuffle"]
let currentIPods = iPods.subtracting(discontinuedIPods)
// ["iPod touch”
交集
let touchscreen: Set = ["iPhone", "iPad", "iPod touch", "iPod nano"]
let iPodsWithTouch = iPods.intersection(touchscreen)
// ["iPod touch", "iPod nano”
并集
var discontinued: Set = ["iBook", "Powerbook", "Power Mac"]
discontinued.formUnion(discontinuedIPods)
discontinued
/*
["iPod shuffle", "iPod Classic", "iPod nano", "Powerbook",
"iPod mini", "Power Mac", "iBook"]
*/”
这里我们使用了可变版本的** formUnion**来改变原来的集合 (正因如此,我们需要将原来的集合用 var 声明)。几乎所有的集合操作都有不可变版本以及可变版本的形式,后一种都以 form 开头。想要了解更多的集合操作,可以看看 SetAlgebra 协议
索引集合和字符集合
Set和OptionSet是标准库中唯一实现SetAlgebra的类型。在Foundation中这个类型也被IndexSet和CharacterSet实现了。
IndexSet 表示了一个由正整数组成的集合。当然,你可以用 Set 来做这件事,但是 IndexSet 更加高效,因为它内部使用了一组范围列表进行实现。打个比方,现在你有一个含有 1000 个元素的 table view,你想要一个集合来管理已经被用户选中的元素的索引。使用 Set 的话,根据选中的个数不同,最多可能会要存储 1000 个元素。而 IndexSet 不太一样,它会存储连续的范围,也就是说,在选取前 500 行的情况下,IndexSet 里其实只存储了选择的首位和末位两个整数值。
不过,作为 IndexSet 的用户,你不需要关心内部实现,所有这一切都隐藏在我们所熟知的SetAlgebra 和 Collection 接口之下,(除非你确实需要直接操作内部的范围,对于这种需求,IndexSet 通过 rangeView 属性暴露了一个它的视图出来,它是一个集合类型)。举例来说,你可以向一个索引集合中添加一些范围,然后对这些索引做 map 操作,就像它们是独立的元素一样:
var indices = IndexSet()
indices.insert(integersIn: 1..<5)
indices.insert(integersIn: 11..<15)
let evenIndices = indices.filter { $0 % 2 == 0 }
// [2, 4, 12, 14]