swift - The elegant solution for function that gives everytime called different element of array(ordered and starting from new when all returned)? -


i newbie , wonder elegant/grown-up solution code be.

i thankful terms can related this, seems common task.

the "1,2,3" are placeholders solution shouldn't rely on them being numbers

var myvalues = [1,2,3] //function, returns 1 element array, in order, , starts  //from beginning when 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 ... 

it not important starts last, 1231231... great!

edit: maybe more descriptive example:

i having 1 clickbutton changes backgroundcolor array of ["red","green","blue"]. when clicking multiple times background turns red, turns green, turns blue, turns red ... not random , not ending.

this process of "popping" iteration... of custom sequence. appropriate way of representing in swift type (struct/class) implements iteratorprotocol. called mine sequencerepeatingiterator. iterators used directly. rather, they're provided type conforms sequence. called mine sequencerepeater

the sequence protocol requires conforming type provide function, makeiterator(), returns iterator (sequencerepeatingiterator in case). doing this, instantly gain of functionality of sequences. iterability, map/filter/reduce, prefix, suffix, etc.

the iteratorprotocol requires type provide function, next(), yields returns element?. return value optional, nil used represent end of sequence.

here how implement these:

struct sequencerepeater<c: collection>: sequence  {     let elements: c          init(repeatingelementsof elements: c) { self.elements = elements }      func makeiterator() -> sequencerepeatingiterator<c> {         return sequencerepeatingiterator(repeatingelementsof: elements)     } }  struct sequencerepeatingiterator<c: collection>: iteratorprotocol {     let elements: c     var elementiterator: c.iterator      init(repeatingelementsof elements: c) {         self.elements = elements         self.elementiterator = elements.makeiterator()     }      mutating func next() -> c.iterator.element? {         guard !elements.isempty else { return nil }          if let nextelement = elementiterator.next() {             return nextelement         }         else {             self.elementiterator = elements.makeiterator()             return self.elementiterator.next()         }     } }  let s1 = sequencerepeater(repeatingelementsof: [1, 2, 3]) //works arrays of numbers, expect. var i1 = s1.makeiterator() print(i1.next() any) //taking 1 element @ time, manually print(i1.next() any) print(i1.next() any) print(i1.next() any) print(i1.next() any) print(i1.next() any) print(i1.next() any)  let s2 = sequencerepeater(repeatingelementsof: 2...5) // works collect. ranges work! print(array(s2.prefix(10))) //taking first 10 elements  let s3 = sequencerepeater(repeatingelementsof: ["a", "b", "c"]) // arrays of strings work, too! s3.prefix(10).map{ "you can map on me! \($0)" }.foreach{ print($0) } 

here's shorter, alternate implementation shows how sequence(state:next:) can used achieve similar thing.

func makecollectionrepeater<c: collection>(for c: c) -> anysequence<c.iterator.element> {     return anysequence(         sequence(state: (elements: c, elementiterator: c.makeiterator()), next: { state in             guard !state.elements.isempty else { return nil }              if let nextelement = state.elementiterator.next() {                 return nextelement             }             else {                 state.elementiterator = state.elements.makeiterator()                 return state.elementiterator.next()             }         })     ) }  let repeater = makecollectionrepeater(for: [1, 2, 3]) print(array(repeater.prefix(10))) 

Comments

Popular posts from this blog

ZeroMQ on Windows, with Qt Creator -

unity3d - Unity SceneManager.LoadScene quits application -

python - Error while using APScheduler: 'NoneType' object has no attribute 'now' -