“弹出”的过程实际上是自定义序列的迭代。在Swift中表示这种情况的适当方式是作为实现的类型(
struct/
class)
IteratorProtocol。我打电话给我
CycleIterator。迭代器很少直接使用。而是通常由符合的类型提供
Sequence。我打电话给我
CycleSequence
该
Sequence协议只需要使用符合条件的类型来提供一个函数
makeIterator(),该函数会返回一个迭代器(
CycleIterator在我的情况下)。只需执行此操作,即可立即获得序列的所有功能。Iterability,
map/
filter/
reduce,
prefix,
suffix等。
在
IteratorProtocol只要求这种类型提供一个函数,
next(),这产生一个返回
Element?。返回值是可选的,
nil用于表示序列的结尾。
这是我将如何实现这些方法:
public struct CycleSequence<C: Collection>: Sequence { public let cycledElements: C public init(cycling cycledElements: C) { self.cycledElements = cycledElements } public func makeIterator() -> CycleIterator<C> { return CycleIterator(cycling: cycledElements) }}public struct CycleIterator<C: Collection>: IteratorProtocol { public let cycledElements: C public private(set) var cycledElementIterator: C.Iterator public init(cycling cycledElements: C) { self.cycledElements = cycledElements self.cycledElementIterator = cycledElements.makeIterator() } public mutating func next() -> C.Iterator.Element? { if let next = cycledElementIterator.next() { return next } else { self.cycledElementIterator = cycledElements.makeIterator() // Cycle back again return cycledElementIterator.next() } }}let s1 = CycleSequence(cycling: [1, 2, 3]) // Works with arrays of numbers, as you would expect.// Taking one element at a time, manuallyvar i1 = s1.makeIterator()print(i1.next() as Any) // => Optional(1)print(i1.next() as Any) // => Optional(2)print(i1.next() as Any) // => Optional(3)print(i1.next() as Any) // => Optional(1)print(i1.next() as Any) // => Optional(2)print(i1.next() as Any) // => Optional(3)print(i1.next() as Any) // => Optional(1)let s2 = CycleSequence(cycling: 2...5) // Works with any Collection. Ranges work!// Taking the first 10 elementsprint(Array(s2.prefix(10))) // => [2, 3, 4, 5, 2, 3, 4, 5, 2, 3]let s3 = CycleSequence(cycling: "abc") // Strings are Collections, so those work, too!s3.prefix(10).map{ "you can even map over me! ($0)" }.forEach{ print($0) }print(Array(CycleSequence(cycling: [true, false]).prefix(7))) // => [true, false, true, false, true, false, true]print(Array(CycleSequence(cycling: 1...3).prefix(7))) // => [1, 2, 3, 1, 2, 3, 1]print(Array(CycleSequence(cycling: "ABC").prefix(7))) // => ["A", "B", "C", "A", "B", "C", "A"]print(Array(CycleSequence(cycling: EmptyCollection<Int>()).prefix(7))) // => []print(Array(zip(1...10, CycleSequence(cycling: "ABC")))) // => [(1, "A"), (2, "B"), (3, "C"), (4, "A"), (5, "B"), (6, "C"), (7, "A"), (8, "B"), (9, "C"), (10, "A")]这是一个简短的替代实现,展示了如何
sequence(state:next:)用于实现相似的目标。
func makeCycleSequence<C: Collection>(for c: C) -> AnySequence<C.Iterator.Element> { return AnySequence( sequence(state: (elements: c, elementIterator: c.makeIterator()), next: { state in if let nextElement = state.elementIterator.next() { return nextElement } else { state.elementIterator = state.elements.makeIterator() return state.elementIterator.next() } }) )}let repeater = makeCycleSequence(for: [1, 2, 3])print(Array(repeater.prefix(10)))


