我是新手,不知道我的代码会是什么样的优雅/成长型解决方案。
我也很感谢我能找到与此相关的术语,这似乎是一项常见的任务。
“ 1,2,3” 只是占位符,因此解决方案不应依赖于它们是数字
var myValues = [1,2,3] //function, that returns one element from array, in order, and starts //from beginning when all elements been returned once,twice etc. func popper() -> Int { let returnValue = myValues.popLast() myValues.insert(returnValue!, at: 0) return returnValue! popper() = 3 popper() = 2 popper() = 1 popper() = 3 ...
以最后一个1231231开始并不重要…也很棒!
编辑:也许更具描述性的示例:
我有一个单击按钮,可从[“ red”,“ green”,“ blue”]数组更改背景色。因此,当多次单击它时,背景变成红色,变成绿色,变成蓝色,变成红色…不是随机的,并且没有结束。
“弹出”的过程实际上是自定义序列的迭代。在Swift中表示这种情况的适当方式是作为实现的类型(struct/ class)IteratorProtocol。我打电话给我CycleIterator。迭代器很少直接使用。而是通常由符合的类型提供Sequence。我打电话给我CycleSequence
struct
class
IteratorProtocol
CycleIterator
Sequence
CycleSequence
该Sequence协议只需要使用符合条件的类型来提供一个函数makeIterator(),该函数会返回一个迭代器(CycleIterator在我的情况下)。只需执行此操作,即可立即获得序列的所有功能。Iterability,map/ filter/ reduce,prefix,suffix等。
makeIterator()
map
filter
reduce
prefix
suffix
在IteratorProtocol只要求这种类型提供一个函数,next(),这产生一个返回Element?。返回值是可选的,nil用于表示序列的结尾。
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, manually var 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 elements print(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:)用于实现相似的目标。
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)))