How to Skip Iterations of a For-In Loop (Swift 3)

How to skip iterations of a for-in loop (Swift 3)

Simple while loop will do

var index = 0

while (index < 100) {
if someCondition(index) {
index += 3 //Skip 3 iterations here
} else {
index += 1
// anything here will not run if someCondition(index) is true
}
}

How to skip an index in a for loop in Swift

The index is automatically incremented in the loop, you can skip an index with a where clause:

for index in 0..<5 where index != 2 {
print(index)
}

Skip to index in for-in loop

In a for loop, you cannot jump the index in real time - that is, if you discover once the loop has started that you need to skip an iteration, you can't. But you can duck out of an iteration with continue. So for example:

var skip = 0
for i in 1...5 {
if i < skip { continue }
print(i)
if i == 2 { skip = 4}
}

In a situation like this, however, you might be happier with a while loop.

var i = 1
while i <= 5 {
print(i)
i += 1
if i == 3 { i = 4 }
}

Another possibility is to unroll the original for loop into a while loop:

var r = (1...5).makeIterator()
while let i = r.next() {
print(i)
if i == 2 { r.next() }
}

All of those are ways of printing 1,2,4,5.

Can you tell a for-loop to conditionally advance by more than one step?

No, you can't change how a for-in loop iterates from within the loop.

A while loop with your own index counter is probably the simplest solution in this case. Though you may be able to make use of sequence(first:next:) in a for-in loop.

How to break/escape from inner loop in Swift

Break just breaks the inner loop.

e.g.

for var i in 0...2
{
for var j in 10...15
{
print("i = \(i) & j = \(j)")
if j == 12
{
break;
}
}
}

Output -->

i = 0 & j = 10
i = 0 & j = 11
i = 0 & j = 12
i = 1 & j = 10
i = 1 & j = 11
i = 1 & j = 12
i = 2 & j = 10
i = 2 & j = 11
i = 2 & j = 12

Any way to stop a block literal in swift

forEach is not a loop (it is a block passed to a loop, but not a loop itself), or more accurately, forEach is not part of Swift's Control Flow. Which is why you can't use break or continue.

Just use a for-in loop.


Example :

var numbers = [ 1,2,3,4]

func firstEvenNumber(inArray array: [Int]) -> Int? {

var firstMatch : Int?

for number in numbers {
if (number % 2) == 0 {
firstMatch = number
break
}
}
return firstMatch
}

firstEvenNumber(inArray: numbers) // 2

You can use return inside the forEach closure, but it does not break the loop, it only returns the block in the current pass.

var numbers = [ 1,2,3,4]

func evenNumbers(inArray: [Int]) -> [Int] {

var matches : [Int] = []

numbers.forEach{
if $0 % 2 == 0 {
matches.append($0)

// early return on even numbers
// does not stop forEach
// comparable to a continue in a for in loop
return
}

// only reached on uneven numbers
}
return matches
}

evenNumbers(numbers) // [2,4]

Counter as variable in for-in-loops

To understand why i can’t be mutable involves knowing what for…in is shorthand for. for i in 0..<10 is expanded by the compiler to the following:

var g = (0..<10).generate()
while let i = g.next() {
// use i
}

Every time around the loop, i is a freshly declared variable, the value of unwrapping the next result from calling next on the generator.

Now, that while can be written like this:

while var i = g.next() {
// here you _can_ increment i:
if i == 5 { ++i }
}

but of course, it wouldn’t help – g.next() is still going to generate a 5 next time around the loop. The increment in the body was pointless.

Presumably for this reason, for…in doesn’t support the same var syntax for declaring it’s loop counter – it would be very confusing if you didn’t realize how it worked.

(unlike with where, where you can see what is going on – the var functionality is occasionally useful, similarly to how func f(var i) can be).

If what you want is to skip certain iterations of the loop, your better bet (without resorting to C-style for or while) is to use a generator that skips the relevant values:

// iterate over every other integer
for i in 0.stride(to: 10, by: 2) { print(i) }

// skip a specific number
for i in (0..<10).filter({ $0 != 5 }) { print(i) }

let a = ["one","two","three","four"]

// ok so this one’s a bit convoluted...
let everyOther = a.enumerate().filter { $0.0 % 2 == 0 }.map { $0.1 }.lazy

for s in everyOther {
print(s)
}

Swift 2: guard in for loop?

There are a few ways to make some conditionals:

You can put a condition for whole for. It will be called for each iteration

for (index, user) in myUsersArray.enumerate() where check() {}
for (index, user) in myUsersArray.enumerate() where flag == true {}

You can check something inside for and skip an iteration or stop the loop:

for (index, user) in myUsersArray.enumerate() {
guard check() else { continue }
guard flag else { break }
}

In your case I will be write something like this:

for (index, user) in myUsersArray.enumerate() {
guard let userId = user.id, userId == myUser.id else { continue }

// do stuff with userId
}

Add a delay to a for loop in swift

You can also use this function to delay something

//MARK: Delay func 

func delay(_ delay:Double, closure:@escaping ()->()) {
DispatchQueue.main.asyncAfter(
deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}

and usage is :

        delay(2)  //Here you put time you want to delay
{
//your delayed code
}

Hope it will help you.



Related Topics



Leave a reply



Submit