我正在寻找迭代器以循环模式无限迭代集合.因此,当达到收集的结束索引时,迭代器应该在start索引处返回元素.
以下解决方案似乎有效,但我希望它可以更好地制作.
public struct LoopIterator<T: Collection>: IteratorProtocol { private let collection: T private var startIndexOffset: T.IndexDistance public init(collection: T) { self.collection = collection startIndexOffset = 0 } public mutating func next() -> T.Iterator.Element? { guard !collection.isEmpty else { return nil } let index = collection.index(collection.startIndex,offsetBy: startIndexOffset) startIndexOffset += T.IndexDistance(1) if startIndexOffset >= collection.count { startIndexOffset = 0 } return collection[index] } } extension Array { func makeLoopIterator() -> LoopIterator<Array> { return LoopIterator(collection: self) } } // Testing... // Will print: 1,2,3,1,3 var it = [1,3].makeLoopIterator() for _ in 0..<6 { print(it.next()) }
这是做自定义迭代器的正确方法吗?有什么可以改进的?
谢谢!
在Swift 3(您正在使用)中,索引旨在由集合本身进行处理.有了它,您可以按如下方式简化:
public struct LoopIterator<Base: Collection>: IteratorProtocol { private let collection: Base private var index: Base.Index public init(collection: Base) { self.collection = collection self.index = collection.startIndex } public mutating func next() -> Base.Iterator.Element? { guard !collection.isEmpty else { return nil } let result = collection[index] collection.formIndex(after: &index) // (*) See discussion below if index == collection.endIndex { index = collection.startIndex } return result } }
现在我们只需向前移动索引,如果它现在指向结尾,则将其重置为开头.无需计数或IndexDistance.
请注意,我在这里使用了formIndex,因为你的Iterator可以处理任何Collection(因此也适用于任何索引),因此可以在某些模糊的情况下(特别是在AnyIndex周围)提高性能.更简单的版本是index = collection.index(after:index),在大多数情况下可能更好.
有关Swift 3指数的所有详细信息,请参阅SE-0065.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。