前言
第 1 章 内建集合类型
第 2 章 集合类型协议(待完成)
第 3 章 可选值(待完成)
第 4 章 结构体和类(待完成)
第 5 章 函数(待完成)
第 6 章 字符串(待完成)
第 7 章 错误处理(待完成)
第 8 章 泛型(待完成)
第 9 章 协议(待完成)
第 10 章 互用性(待完成)
数组
数组和可变性
- 数组
Array
是值类型。Foundation
下的NSArray
是引用类型。如:
let a = NSMutableArray(array: [1,2,3])
// 尽管我们不想让 b 改变
let b = a
a.insert(5, at: 0)
// 可是因为 NSArray 的引用特性,b 依然变了
print(b) // 5 1 2 3
// 如果真的就是用 NSArray,还不想让改变
let c = a.copy() as! NSArray
a.insert(10, at: 0)
print(c) // 5 1 2 3
-
Array
是值复制,但是用了写时复制
的技术,在被拷贝的数据修改前,他们共享内存。之后会有写时拷贝
的更多说明。
数组和可选值
- 想要寻找一个指定元素的位置?
if let index = array.index { someMatchingLogic($0) }
- 想要筛选出某个符合标准的元素集合?
array.filter { soneCCriteria($0) }
数组变形
Map
-
Map
来自函数式编程的世界,使用方法如下:let fibs = [0, 1, 2, 3, 5] let squares = fibs.map { $0 * $0 }
-
Map
的函数签名:@inlinable public func map
(_ transform: (Element) throws -> T) rethrows -> [T]
使用函数将行为参数化
简单来说,就是接收一个函数,作为参数来处理具体事务,简化对外逻辑。例如:
extension Sequence {
func last(where predicate: (Iterator.Element) -> Bool) -> Iterator.Element? {
for element in reversed() where predicate(element) {
return element
}
return nil
}
}
Filter
-
filter
应该只用于,需要知道数组所有结果的时候,因为filter
回创建一个全新的数组。 - 如果仅仅是查询是否包含,用
contains
效率高得多。
Reduce
reduce
用于对数组中所有元素做相加操作,可以使字符、数字、集合等,功能很强大, 这里只举个简单的例子吧:
let fibs = [0, 1, 2, 3, 5]
let new = fibs.reduce(2, +)
// new = 13
flatMap
@available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
public func flatMap(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
flatMap
在 Swift4.1
时被取消了。替代方法,官方也举了个简单的例子:
let possibleNumbers = ["1", "2", "three", "///4///", "5"]
let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
// [1, 2, nil, nil, 5]
let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
// [1, 2, 5]
forEach
使用 forEach
进行迭代要特别注意一点,就是使用 return
语句仅仅是从闭包返回,不会终止循环,譬如:
(1 ..< 10).forEach { (num) in
print(num)
if num > 2 { return }
}
会打印出所有数字,关于 forEach
,官方方法定义中有如下描述
- You cannot use a
break
orcontinue
statement to exit the current call of thebody
closure or skip subsequent calls.- Using the
return
statement in thebody
closure will exit only from the current call tobody
, not from any outer scope, and won't skip subsequent calls.
数组类型
切片
切片类型只是数组的一中表示形式,它背后的数据类型仍然是原来的数组。对于庞大的数组,切片可以理解为对数组的片段预览,并不是重新生成一份内存。具体可看对 ArraySlice
的官方注释:
The
ArraySlice
type makes it fast and efficient for you to perform operations on sections of a larger array. Instead of copying over the elements of a slice to new storage, anArraySlice
instance presents a view onto the storage of a larger array. And becauseArraySlice
presents the same interface asArray
, you can generally perform the
字典
可变性
记着一点即可,字典是值类型。
有用的字典扩展
- 合并两个字典,相同
key
则更新value
:
extension Dictionary {
// 合并数组
mutating func merge(_ other: S) where S: Sequence, S.Iterator.Element == (key: Key, value: Value) {
for (k, v) in other {
self[k] = v;
}
}
}
- 从一个
(key, value)
键值对序列来创建字典:
extension Dictionary {
/// 合并数组
mutating func merge(_ other: S) where S: Sequence, S.Iterator.Element == (key: Key, value: Value) {
for (k, v) in other {
self[k] = v;
}
}
/// 从一个 `(key, value)` 键值对序列来创建字典
init(_ sequence: S) where S.Iterator.Element == (key: Key, value: Value) {
self = [:]
self.merge(sequence)
}
}
- 添加
map
转换
重点:
以上方法, 现在均已加入 Dictionary
标准库。。。并且还更新了很多快捷的系统方法。
Set
集合 Set
是一组无序的元素集合。每个元素仅出现一次。和 Dictionary
一样,Set
也是通过哈希表实现的。
集合代数
集合 Set
和数学上的集合有着密切的关系,可以求两个集合的交集、并集等。
在闭包中使用集合
获取一个序列中的所有唯一元素:
extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
var seen: Set = []
return filter {
if seen.contains($0) {
return false
} else {
seen.insert($0)
return true
}
}
}
}
print([1,2,3,5,21,12,5,3,2].unique()) // [1, 2, 3, 5, 21, 12]
Range
在标准库中,目前有四种范围类型:
描述 | 半开范围 | 闭合范围 |
---|---|---|
元素满足 Comparable |
Range |
CloseRange |
元素满足 Strideable (以整数为步长) |
CountableRange |
CountableCloseRange |
- 只有 半开范围 能表达 空区间 的概念。(当范围的上下边界相等时,比如
5 ..< 5
)。 - 只有 闭合范围 能够包含它的元素类型所能表达的最大值。半开范围总是至少会有一个值比范围所表达的值更大。
总结
希望这几天能坚持把这本书分章梳理完,更多的扩展 Swift
知识面,加深印象,对于特别细的知识点,这里不做展开。