Home > Back-end >  iOS/Swift: How to add 1 to i in a loop for for a specific value and how to retrograd a 'loop fo
iOS/Swift: How to add 1 to i in a loop for for a specific value and how to retrograd a 'loop fo

Time:10-07

I try to add 1 to i in a loop for in a specific moment? When I do this, it comes to the "normal" value instantly at the begining of the loop.

for var i in (0..<10)
    {
    if (i == 2)
       {
       i  = 1
       }
    }

EDIT:

Concret code:

                   for var i in (0..<models.count) 
                    {
                        if (i > 0 && models[i].label1 == models[i-1].label1)
                        {
                            models[i-1].slots.append(contentsOf: models[i].slots)
                            models.remove(at: i)
                            i -= 1
                           
                        }
                    }

CodePudding user response:

In for loops in Swift, the variable (i) is treated as a let constant, and you cannot mutate it inside the loop.

That seems right. Being able to mutate a loop variable inside the loop can lead to all sorts of unexpected side-effects.

You can use a while loop to get the same effect:

The following works:

var i = 0
while i < 10  {
    print(i)
    if i.isMultiple(of: 2) && Int.random(in: 1...3) == 2 {
        i -= 1
    }
    i  = 1
}
print("Done")

This code throws a compiler error:

for index in 1...10 {
    if index.isMultiple(of: 3) {
        index  = 1 // <- Error: "left side of mutating operator isn't mutable: 'index' is a 'let' constant"
        print(index)
    }
}

CodePudding user response:

The for loop sets the value of i each time through.

So,

    for var i in (0..<10)
    {
        // the for loop sets i to the next value in 0 to 9
        print(i)
        if (i == 2)
        {
            // print current value of i
            print("a:", i)
            i  = 1
            // print current value of i
            print("b:", i)
        }
    }

Inside your if (i == 2) block, you change the value of i but then the for loop changes it right back to the next value in the enumeration of 0 to 9.

The debug output from the above code will look like this:

0
1
2
a: 2
b: 3
3
4
5
6
7
8
9

To make it more obvious, change i = 1 to i = 4

Output:

0
1
2
a: 2
b: 6
3
4
5
6
7
8
9

CodePudding user response:

The problem is caused because the i is scoped to the block of the loop. Each time round you actually get a new i.

There are three solutions.

The first is to use a while loop as per Duncan C's answer.

The second is to maintain a separate index and still use a for loop, but that's really just the same as the first one

The best answer IMO is to count downwards from the end.

for i in (1 ..< models.count).reversed()
{
    if (models[i].label1 == models[i-1].label1)
    {
        models[i-1].slots.append(contentsOf: models[i].slots)
        models.remove(at: i)
    }
}

Of course, reversing a list of numbers gets expensive for long lists, so you might consider using stride

for i in stride(from: models.count - 1, to: 0, by: -1)
{
    if (models[i].label1 == models[i-1].label1)
    {
        models[i-1].slots.append(contentsOf: models[i].slots)
        models.remove(at: i)
    }
}
  • Related