ios - How to detect the first run of an IteratorProtocol in swift?
问题描述
Trying to detect the first run of an Iterator protocol. In the example below I'm trying to start printing Fibonacci series from Zero but it starts from One:
class FibIterator : IteratorProtocol {
var (a, b) = (0, 1)
func next() -> Int? {
(a, b) = (b, a + b)
return a
}
}
let fibs = AnySequence{FibIterator()}
print(Array(fibs.prefix(10)))
What modifications can be made to the above code to detect the first run?
解决方案
To answer your verbatim question: You can add a boolean variable
firstRun
to detect the first call of the next()
method:
class FibIterator : IteratorProtocol {
var firstRun = true
var (a, b) = (0, 1)
func next() -> Int? {
if firstRun {
firstRun = false
return 0
}
(a, b) = (b, a + b)
return a
}
}
let fibs = AnySequence { FibIterator() }
print(Array(fibs.prefix(10))) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
But there are more elegant solutions for this problem.
You can “defer” the update of a
and b
to be done after returning
the current value:
class FibIterator : IteratorProtocol {
var (a, b) = (0, 1)
func next() -> Int? {
defer { (a, b) = (b, a + b) }
return a
}
}
let fibs = AnySequence { FibIterator() }
print(Array(fibs.prefix(10))) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
or – perhaps simpler – change the initial values (using the fact that the Fibonacci numbers are defined for negative indices as well):
class FibIterator : IteratorProtocol {
var (a, b) = (1, 0) // (Fib(-1), Fib(0))
func next() -> Int? {
(a, b) = (b, a + b)
return a
}
}
let fibs = AnySequence { FibIterator() }
print(Array(fibs.prefix(10))) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Note that if you declare conformance to the Sequence
protocol
then you don't need the AnySequence
wrapper (there is a default
implementation of makeIterator()
for types conforming to
IteratorProtocol
). Also value types are generally preferred,
so – unless the reference semantics is needed – you can make it a struct
:
struct FibSequence : Sequence, IteratorProtocol {
var (a, b) = (1, 0) // (Fib(-1), Fib(0))
mutating func next() -> Int? {
(a, b) = (b, a + b)
return a
}
}
let fibs = FibSequence()
推荐阅读
- powershell - 在 get-Childitem -Recurse 期间将暂停的 PowerShell 命令行
- bitbucket - 无法使用 Bitbucket API 2.0 在存储库中创建新分支
- google-cloud-platform - 如何修改/检查谷歌云运行失败的重试限制?
- postgresql - 访问 Postgres 数据库容器但出现错误
- android - 如何在 kotlin 中使用侧面菜单在 mvvm 中获取系统后退按钮
- html - 如何在不浏览图像而不是单击一个按钮的情况下将图像从系统上传到角度项目?
- laravel - 在 Laravel 中编写长查询的惯用方式?
- python-3.x - pyzk如何获取实时捕获的结果
- android - Android Media Player 无法按路径播放音频文件
- excel - 使用相同数据绘制 2 个或多个单独的图形时,VBA 中的图形缺失部分