Swift进阶:内建集合类型

前言

第 1 章 内建集合类型

第 2 章 集合类型协议(待完成)

第 3 章 可选值(待完成)

第 4 章 结构体和类(待完成)

第 5 章 函数(待完成)

第 6 章 字符串(待完成)

第 7 章 错误处理(待完成)

第 8 章 泛型(待完成)

第 9 章 协议(待完成)

第 10 章 互用性(待完成)

数组

数组和可变性

  1. 数组 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
  1. Array 是值复制,但是用了 写时复制 的技术,在被拷贝的数据修改前,他们共享内存。之后会有 写时拷贝 的更多说明。

数组和可选值

  • 想要寻找一个指定元素的位置? if let index = array.index { someMatchingLogic($0) }
  • 想要筛选出某个符合标准的元素集合? array.filter { soneCCriteria($0) }

数组变形

Map

  1. Map 来自函数式编程的世界,使用方法如下:
    let fibs = [0, 1, 2, 3, 5]
    let squares = fibs.map { $0 * $0 }
    
  2. 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

  1. filter 应该只用于,需要知道数组所有结果的时候,因为 filter 回创建一个全新的数组。
  2. 如果仅仅是查询是否包含,用 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]

flatMapSwift4.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,官方方法定义中有如下描述

  1. You cannot use a break or continue statement to exit the current call of the body closure or skip subsequent calls.
  2. Using the return statement in the body closure will exit only from the current call to body, 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, an ArraySlice instance presents a view onto the storage of a larger array. And because ArraySlice presents the same interface as Array, you can generally perform the

字典

可变性

记着一点即可,字典是值类型。

有用的字典扩展

  1. 合并两个字典,相同 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;
        }
    }
}
  1. 从一个 (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)
    }
}
  1. 添加 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 知识面,加深印象,对于特别细的知识点,这里不做展开。

你可能感兴趣的:(Swift进阶:内建集合类型)