关于如何在Swift中创建生成器(或者 iterators ,因为它们显然在Swift中调用)的指南很少,特别是如果您不熟悉该语言。为什么有AnyIterator
和UnfoldSequence
这么多的生成器类型?为什么以下代码不应该从单个Int
的序列或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)
}
我理解它的方式,AnyIterator
应该在{}
s中进行闭包并将其转换为返回的生成器中的.next()
方法,但它似乎不是工作。或者我应该在this question中使用UnfoldSequence
代替。我很困惑。
答案 0 :(得分:4)
是的,next()
AnyIterator
方法会调用给定的闭包。
在你的代码中,该闭包在每次调用时返回相同的第一个元素,因为它不记得已经返回了哪些元素。
如果Swift有一个yield
语句,比如Python或C#那么事情会更容易:你可以yield segment
或yield i
完成。
但是 - 不幸的是? - Swift没有yield
语句,这意味着
闭包必须显式管理某些状态才能恢复迭代
每次通话都有下一个元素。
一种可能性是维持两个指数,一个用于 当前段和当前元素之一 一个段,如果是一个数组:
func chain(_ segments: Any...) -> AnyIterator<Int> {
var currentSegment = 0 // index of current segment
var currentElement = 0 // index of current element within current segment
return AnyIterator<Int> {
while currentSegment < segments.count {
let next = segments[currentSegment]
switch next {
case let value as Int:
currentSegment += 1
return value
case let segment as [Int]:
if currentElement < segment.count {
let val = segment[currentElement]
currentElement += 1
return val
}
currentSegment += 1
currentElement = 0
default:
return nil
}
}
return nil
}
}
这可以推广到任意嵌套的数组:
func chain(_ segments: Any...) -> AnyIterator<Int> {
var stack: [(Any, Int)] = [(segments, 0)]
return AnyIterator<Int> {
while let (next, idx) = stack.popLast() {
switch next {
case let value as Int:
return value
case let segments as [Any]:
if idx < segments.count {
stack.append((segments, idx + 1))
stack.append((segments[idx], 0))
}
default:
return nil
}
}
return nil
}
}
待处理数组仍在堆栈中 他们目前的指数。数组本身不会被修改, 这样副本很便宜。
示例:
let G = chain([1, 2, [3]], 4, [5, 6, [], 7])
while let g = G.next() {
print(g)
}
// 1 2 3 4 5 6 7
有关详情,另请参阅Implementing recursive generator for simple tree structure in Swift 递归枚举树状结构的方法。
答案 1 :(得分:0)
您还可以查看此迭代器的自定义实现,如https://stackoverflow.com/a/67215766/5867877
class ArrayIterator<T>{
private var array : [T] = []
private var stepSize: Int = 10
private var head: Int = 0
var hasNext: Bool {
get {
return head < array.count
}
}
class func from(array: [T], stepSize size: Int = 10, startingAt startIndex: Int = 0) -> ArrayIterator<T>{
let a = ArrayIterator<T>()
a.array = array
a.stepSize = size
a.head = startIndex
return a
}
func next() -> Array<T>? {
guard head < array.count else {
return nil
}
defer {
head = head + stepSize
}
guard stepSize < array.count else {
return array
}
if let _ = array[safe: (head + stepSize - 1)] {
return Array(array[head..<head + stepSize])
} else {
let remaider = (head + stepSize - 1) % array.count
return Array(array[head..<(head + stepSize - 1 - remaider)])
}
}