关于如何在Swift中创建生成器(或者在Swift中显然调用它们的迭代器)的指南很少,特别是如果您不熟悉该语言.为什么有这么多的发电机类型AnyIterator和UnfoldSequence?为什么下面的代码不应该从单个Ints或s的数组中产生Int?
func chain(_ segments: Any...) -> AnyIterator<Int>{
return AnyIterator<Int> {
for segment in segments {
switch segment {
case let segment as Int:
return segment
case let segment as [Int]:
for i in segment {
return i
}
default:
return nil
}
}
return nil
}
}
let G = chain(array1, 42, array2)
while let g = G.next() {
print(g)
}
Run Code Online (Sandbox Code Playgroud)
我理解它的方式,AnyIterator应该采取{}s中的闭包并将其转换.next()为返回的生成器中的方法,但它似乎不起作用.或者我应该UnfoldSequence像这个问题一样使用.我很困惑.
是的, 的next()方法AnyIterator调用给定的闭包。\n在您的代码中,该闭包在每次调用时返回相同的第一个元素,因为它不记得已经返回了哪些元素。
如果 Swift 有yield像 Python 或 C# 这样的语句,那么事情会更容易:你可以yield segment或yield i已经完成了。
但不幸的是\xe2\x80\x93?\xe2\x80\x93 Swift 没有yield语句,这意味着闭包必须显式管理某些状态,以便在每次调用时恢复与下一个元素的迭代。
一种可能是维护两个索引,一个用于当前段,一个用于段内的当前元素(如果该索引是数组):
\n\nfunc chain(_ segments: Any...) -> AnyIterator<Int> {\n var currentSegment = 0 // index of current segment\n var currentElement = 0 // index of current element within current segment\n return AnyIterator<Int> {\n while currentSegment < segments.count {\n let next = segments[currentSegment]\n switch next {\n case let value as Int:\n currentSegment += 1\n return value\n case let segment as [Int]:\n if currentElement < segment.count {\n let val = segment[currentElement]\n currentElement += 1\n return val\n }\n currentSegment += 1\n currentElement = 0\n default:\n return nil\n }\n }\n return nil\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这可以推广到任意嵌套的数组:
\n\nfunc chain(_ segments: Any...) -> AnyIterator<Int> {\n var stack: [(Any, Int)] = [(segments, 0)]\n return AnyIterator<Int> {\n while let (next, idx) = stack.popLast() {\n switch next {\n case let value as Int:\n return value\n case let segments as [Any]:\n if idx < segments.count {\n stack.append((segments, idx + 1))\n stack.append((segments[idx], 0))\n }\n default:\n return nil\n }\n }\n return nil\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n仍待处理的数组与其当前索引一起位于堆栈上。数组本身不会被修改,\n因此副本很便宜。
\n\n例子:
\n\nlet G = chain([1, 2, [3]], 4, [5, 6, [], 7])\nwhile let g = G.next() {\n print(g)\n}\n// 1 2 3 4 5 6 7\nRun Code Online (Sandbox Code Playgroud)\n\n另请参阅在 Swift 中实现简单树结构的递归生成器,了解更多\n递归枚举树状结构的方法。
\n| 归档时间: |
|
| 查看次数: |
1370 次 |
| 最近记录: |