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)
}
}