Sequence
Sequence是一系列相同类型的值的集合,并且提供对这些值得迭代能力
迭代一个Sequence最常见的方式就是for-in,并且提供对这些值得迭代能力
for element in someSequence {
doSomething(with: element)
}
我们经常把for-in循环用到Array,Dictonary,set等数据结构中,那是因为它们都是实现了Sequence协议。
Sequence协议的定义:
protocol Sequence{
associatedtype Iterator:IteratorProtocol
func makeIterator()->Iterator
}
Sequence的协议里只有一个必须实现的方法就是makeIterator(),
makeIterator()需要返回一个Iterator,他就是一个IteratorProtocol类型。
只要提供一个Iterator就能实现Sequence,那么Iterator又是什么了???
Iterator
Iterator 在 Swift 3.1 标准库中即为 IteratorProtocol,它用来为 Sequence 提供迭代能力。对于 Sequence,我们可以用for-in来迭代其中的元素,其实for-in的背后是 IteratorProtocol 在起作用。
IteratorProtocol 的定义如下:
public protocol IteratorProtocol{
associatedtype Element
public mutating func next()->Self.Element?
}
associatedtype 声明了元素的类型
next()用来返回Sequence中的下一个元素,或者当没有了下一个元素就返回nil
Iterator实现举例说明
举例1
struct SimplestIterator:IteratorProtocol {
typealias Element = Int
mutating func next() -> Int? {
return nil
}
}
这个例子中的Iterator不会迭代出任何元素,确切的说,这个Iterator在迭代时仅调用一次next()就结束了。
举例2
struct ConstantIterator:IteratorProtocol {
typealias Element = Int
mutating func next() -> Int? {
return 1
}
}
这个一直迭代出的是1
实现一个Sequence
实现一个Sequence首先要实现一个Iterator
实现一个Iterator,接收一个字符串数组,并可以迭代这个数组中的所有字符串的首字母,当数组中的最后一个字符串迭代完后迭代完成,退出迭代
struct FirstLetterIterator:IteratorProtocol {
typealias Element = String
let stringArr:[String]
var offset:Int
init(strings:[String]) {
stringArr = strings
offset = 0
}
mutating func next() -> String? {
guard offset < stringArr.endIndex else {
return nil
}
let string = stringArr[offset]
offset += 1
return string.substring(to: string.index(string.startIndex, offsetBy: 1))
}
}
这个Iterator的需要输入一个字符串数组,在哪next()中,判断边界,并返回数组为offset的字符串的首字母,并将offset加1
有了实现好的Iterator,就可以简单的用他实现Sequence,在makeIterator()中返回这个Iterator即可
struct FirstLetterSequence:Sequence {
let strngs:[String]
func makeIterator() -> FirstLetterIterator {
return FirstLetterIterator(strings:strngs)
}
}
现在Sequence已经实现完成了,
for letter in FirstLetterSequence(strngs:["apple","banana","orange"]) {
print(letter)
}
打印结果:
a
b
o
值类型 Iterator 和引用类型 Iterator
值类型 Iterator
一般 Iterator 都是值类型的,值类型的 Iterator 的意思是:当把 Iterator 赋值给一个新变量时,是把原 Iterator 的所有状态拷贝了一份赋值给新的 Iterator,原 Iterator 在继续迭代时不会影响新的 Iterator。
例如用stride函数创建一个简单的 Sequence,它从 0 开始,到 9 截止,每次递增 1,即为 [0, 1, 2, ..., 8, 9]。
然后获取到它的 Iterator,调用 next() 进行迭代。
let seq = stride(from: 0, to: 10, by: 1)
var i1 = seq.makeIterator()
print(i1.next())
print(i1.next())
输出结果
Optional(0)
Optional(1)
然后做一个赋值操作,建一个新的i2
var i2= i1
然后输出
print(i1.next())
print(i1.next())
print(i2.next())
print(i2.next())
输出结果
Optional(0)
Optional(1)
Optional(0)
Optional(1)
这里的i1和i2相互不影响,赋值对i1做了一份完整的拷贝,这里的Iterator是一个值类型的Iterator
应用类型的Iterator
可以把任何一个值类型 Iterator 用AnyIterator这个包一下就形成了一个引用类型的 Iterator。
var i3 = AnyIterator(i1)
var i4 = i3
输出
print(i3.next())
print(i4.next())
print(i3.next())
print(i4.next())
输出结果
Optional(0)
Optional(1)
Optional(2)
Optional(3)
引用类型的 Iterator,再赋值给一个新的变量后,新的 Iterator 和原 Iterator 在进行迭代时会互相对对方产生影响。
学习博客参考
Swift 中的 Sequence(一)
Swift 中的 Sequence(二)