Swift - 内联序列函数sequence介绍(附样例)
Swift 3 新增了两个全局函数:sequence(first: next:) 和 sequence(state: next:)。使用它们可以返回一个无限序列。我们可以给他们一个初始值,或者初始状态,然后他们便会以懒加载的方式应用到一个闭包。下面通过样例分别演示这两个函数如何使用。
1,sequence(first: next:)介绍
//函数声明 public func sequence<t>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)>其作用是通过设置的初始值 first,循环得到 next(first)、next(next(first))、next(next(next(first)))......
假设我们打印出从1到100范围内所有的2的n次方数,过去我们使用 repeat...while 可以这么写:
var i = 1
repeat {
print(i)
i = i * 2
} while i <= 100
输出结果:

可以看到 repeat...while 循环依赖我外面声明的一个变量 i。
(1)而改用 sequence(first: next:) 实现如下,可以看到省去了外部变量的定义。
for i in sequence(first: 1, next: { $0 * 2 }) {
if i > 100 { break }
print(i)
}
(2)我们还可以将所有的处理逻辑,状态判断都放在 next 闭包里。所以上面样例又可以这样写。
for _ in sequence(first: 1, next: {
print($0)
let value = $0 * 2
return value <= 100 ? value : nil //next中返回nil表示sequence结束
}) {}
(3)从某一个树节点一直向上遍历到根节点
for node in sequence(first: leaf, next: { $0.parent }) {
// node is leaf, then leaf.parent, then leaf.parent.parent, etc.
}
2,sequence(state: next:)
//函数声明
public func sequence<T, State>(state: State, next: @escaping (inout State) -> T?)
-> UnfoldSequence<T, State>
这个方法是设置个初始状态(可变的),后面将其传 入next 闭包改变状态,并获取下一个序列,依次类推。
(1)下面样例通过指定最大的x轴,y轴坐标值,列出其内部所有的整点。

import UIKit
class ViewController: UIViewController {
//命名一个坐标点类型
typealias PointType = (x: Int, y: Int)
override func viewDidLoad() {
super.viewDidLoad()
//遍历序列并打印出所有坐标
for point in cartesianSequence(xCount: 5, yCount: 3) {
print("(x: \(point.x), y: \(point.y))")
}
}
//返回所有符合条件的坐标点序列
func cartesianSequence(xCount: Int, yCount: Int) -> UnfoldSequence<PointType, Int> {
assert(xCount > 0 && yCount > 0,
"必须使用正整数创建序列。")
return sequence(state: 0, next: {
(index: inout Int) -> PointType? in
guard index < xCount * yCount else { return nil }
defer { index += 1 }
return (x: index % xCount, y: index / xCount)
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
运行结果如下:

(2)假设我们有两个书架,一个里面是中文书、另一个里面是外文书。现在要返回一个交叉序列,即一本中文书、一本外文书这样交替显示。直到某个书柜的书显示完毕即结束。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//中文书架
let bookShelf1 = BookShelf()
bookShelf1.append(book: Book(name: "平凡的世界"))
bookShelf1.append(book: Book(name: "活着"))
bookShelf1.append(book: Book(name: "围城"))
bookShelf1.append(book: Book(name: "三国演义"))
//外文书架
let bookShelf2 = BookShelf()
bookShelf2.append(book: Book(name: "The Kite Runner"))
bookShelf2.append(book: Book(name: "Cien anos de soledad"))
bookShelf2.append(book: Book(name: "Harry Potter"))
//创建两个书架图书的交替序列
for book in sequence(state: (false, bookShelf1.makeIterator(), bookShelf2.makeIterator()),
next: { (state:inout (Bool,AnyIterator<Book>,AnyIterator<Book>)) -> Book? in
state.0 = !state.0
return state.0 ? state.1.next() : state.2.next()
}) {
print(book.name)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
// 图书
struct Book {
var name: String
}
// 书架
class BookShelf {
//图书集合
private var books: [Book] = []
//添加新书
func append(book: Book) {
self.books.append(book)
}
//创建Iterator
func makeIterator() -> AnyIterator<Book> {
var index : Int = 0
return AnyIterator<Book> {
defer {
index = index + 1
}
return index < self.books.count ? self.books[index] : nil
}
}
}
运行结果如下:
