2

I have below code.

var myArray : [String] = ["1", "2", "3", "4", "5"]
for var i in 0..<myArray.count {
    print("i==\(i)==\(myArray[i])")
    myArray.remove(at: i)
    i = i-1
}

Log is as below.

i==0==1
i==1==3
i==2==5
fatal error: Index out of range

Log I was expecting is

i==0==1
i==0==2
i==0==3
i==0==4
i==0==5

I am saying this because when I set i=i-1 in the for loop, i will be always 0.

Which means variable i is not having effect of code i=i-1

Any idea why this is happening?


Same code I have in java, and it works fine.

ArrayList<String> mm = new ArrayList<>();
mm.add("1");
mm.add("2");
mm.add("3");
mm.add("4");
mm.add("5");

for(int i=0; i<mm.size(); i++){

    Log.d("mm", "i=="+i+"=="+mm.get(i));

    mm.remove(i);

    i = i-1;

}

Log I have is as below

i==0==1
i==0==2
i==0==3
i==0==4
i==0==5
Fahim Parkar
  • 30,974
  • 45
  • 160
  • 276
  • _"I am saying this because when I set i=0 in the for loop, it should not come in second loop."_ Why not? Btw this is the correct output for your code. – Rakesha Shastri Dec 04 '18 at 09:17
  • Explanation is quite clear here: https://stackoverflow.com/questions/11905606/changing-the-number-of-iterations-in-a-for-loop – prex Dec 04 '18 at 09:30
  • 1
    You need iterate your collection reverse order – Leo Dabus Dec 04 '18 at 09:31
  • @RakeshaShastri : I have updated question... Please check... – Fahim Parkar Dec 04 '18 at 09:32
  • Btw, is that code just hypothetical experiment on language or it supposed to be used in real project? Because removing elements from collection you're currently iterating while accessing it by index is always a bad idea. – user28434'mstep Dec 04 '18 at 10:05

1 Answers1

4

Swift for loops work a bit differently than you think.

First thing to note that the bit after the in is evaluated only once. It doesn't get the array's count in every iteration. 0..<array.count can totally be replaced with 0..<5 and the result will be no different.

Second thing is that even though you set i in the loop, i's value won't be the value you set in the next iteration. This is because at the start of each iteration, i is assigned the next element in the sequence. This means that whatever you assign to i, i will only hold that value until the end of the current iteration.

Now, we can explain the output.

First iteration, i is 0 so element at index 0 gets printed. The 1st element is removed. Array is now ["2", "3", "4", "5"].

Second iteration, i is 1 so element at index 1 gets printed (3). The 2nd element is removed. Array is now ["2", "4", "5"].

Third iteration, i is 2 so element at index 2 gets printed (5). The 3rd element is removed. Array is now ["2", "4"].

Fourth iteration, i is 3 but the array is only 2 elements long, so index out of range.

Rakesha Shastri
  • 11,053
  • 3
  • 37
  • 50
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • `Second thing` is what I was thinking.. So just to confirm, this behavior is part of Swift. – Fahim Parkar Dec 04 '18 at 09:34
  • 2
    @FahimParkar it is part of swift. `for...in` loops of most other languages I know of have this behaviour too. It’s the C style for loops that doesn’t do this. – Sweeper Dec 04 '18 at 09:36