Search code examples
iosarraysswiftfor-loopswift3

How do I write a for-loop in Swift 3 for an array that I modify during the for loop?


So, I have a for-loop that looks similar to this:

for var i = 0; i < results.count ; i += 1 {
   if (results[i] < 5) {
      results.removeAtIndex(i)
      i -= 1
   }
}

This used to work. But when I changed it to the preferred Swift 3.0 syntax:

for var i in 0..<results.count {
   if (results[i] < 5) {
      results.removeAtIndex(i)
      i -= 1
   }
}

I get an array IOOBE exception because it doesn't re-check the count and continues on until the original results.count.

How do I fix this? It works now, but I don't want to get into trouble in the future.


Solution

  • While the solution making use of filter is a fine solution and it's more Swift-ly, there is another way, if making use of for-in is, nonetheless, still desired:

    func removeBelow(value: Int) {
        var results = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
        for i in (0 ..< results.count).reversed() {
            if (results[i] < value) {
                results.remove(at: i)
            }
        }
    
        print(results)
    }
    
    removeBelow(value: 5)
    

    Result:

    [5, 6, 7, 8, 9, 10]
    

    The problem with removeAtIndex within the loop is that it will not cause the array to re-index itself in-place and thus causing an array out of bounds exception due to count not being updated.

    By traversing backwards, the out of bounds exception can thus be avoided.