Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a non-C-like for-loop in Swift 2.2+?

I have updated Xcode (7.3) and there are a lot of changes; C-like for expressions will be deprecated. For a simple example,

for var i = 0;  i <= array.count - 1;  i++
 {
      //something with array[i]
 } 

How do I write this clear and simple C-like for-loop to be compliant with the new changes?

for var i = 0, j = 1;  i <= array.count - 2 && j <= array.count - 1;  i++, j++
{
     //something with array[i] and array[j]
}  

Update. One more variant

for var i = 0; i <= <array.count - 1; i++
{
    for var j = i + 1; j <= array.count - 1; j++
    {
        //something with array[i] and array[j]
    }
}

And more ...

for var i = 0, j = 1, g = 2;  i <= array.count - 3 && j <= array.count - 2 &&   g <= array.count - 1;  i++, j++, g++
{
     //something with array[i] and array[j] and array[g]
} 

Update2 After several suggestions for me while loop is preferable universal substitution for all cases more complicated than the simple example of C-like for-loop (suitable for for in expression). No need every time to search for new approach.
For instance: Instead of

for var i = 0; i <= <array.count - 1; i++
{
    for var j = i + 1; j <= array.count - 1; j++
    {
        //something with array[i] and array[j]
    }
}

I can use

var i = 0
while i < array.count
{
    var j = i + 1
    while j < array.count
    {
        //something with array[i] and array[j]
        j += 1
    }
    i += 1
}
like image 959
VYT Avatar asked Mar 22 '16 13:03

VYT


Video Answer


3 Answers

charl's (old) answer will crash. You want 0..<array.count:

for index in 0..<array.count {
    // ...
}

If you want something like your i/j loop you can use stride and get i's successor:

for i in 0.stride(through: array.count, by: 1) {
    let j = i.successor()
    // ...
}

Just make sure to check i.successor() in case you go out of bounds.

like image 196
JAL Avatar answered Oct 19 '22 07:10

JAL


for var i = 0;  i <= array.count - 1;  i++ {
      //something with array[i]
 }

Here you don't need the element index at all, so you can simply enumerate the array elements:

for elem in array {
    // Do something with elem ...
}

for var i = 0, j = 1;  i <= array.count - 2 && j <= array.count - 1;  i++, j++ {
     //something with array[i] and array[j]
}

To iterate over pairs of adjacent elements, use zip() and dropFirst():

for (x, y) in zip(array, array.dropFirst()) {
    // Do something with x and y ...
    print(x, y)
}

Output:

1 2
2 3
3 4
4 5

For other distances, use dropFirst(n):

for (x, y) in zip(array, array.dropFirst(3)) {
    // Do something with x and y ...
    print(x, y)
}

Output:

1 4
2 5

There are probably many solutions to do

for var i = 0; i <= <array.count - 1; i++ {
    for var j = i + 1; j <= array.count - 1; j++ {
        //something with array[i] and array[j]
    }
}

without a C-style for-loop, here is one:

for (index, x) in array.enumerate() {
    for y in array.dropFirst(index + 1) {
        print(x, y)
    }
}
like image 28
Martin R Avatar answered Oct 19 '22 08:10

Martin R


If you want to do something with subsequent pairs there are many other ways to do it.

Something like this would work...

var previousItem = array.first

for index in 1..<array.count {
    let currentItem = array[index]

    // do something with current and previous items

    previousItem = currentItem
}
like image 2
Fogmeister Avatar answered Oct 19 '22 07:10

Fogmeister