swift – 自定义迭代器,以循环模式无限迭代集合
发布时间:2020-12-14 02:27:04 所属栏目:百科 来源:网络整理
导读:我正在寻找迭代器以循环模式无限迭代集合.因此,当达到收集的结束索引时,迭代器应该在start索引处返回元素. 以下解决方案似乎有效,但我希望它可以更好地制作. public struct LoopIteratorT: Collection: IteratorProtocol { private let collection: T privat
我正在寻找迭代器以循环模式无限迭代集合.因此,当达到收集的结束索引时,迭代器应该在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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |