C-Style for Loop in Swift 2

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

Worst case, you can convert it to a while loop.

var i = 0
var j = 1
while i <= array.count -2 && j <= array.count - 1 {
// something
i += 1
j += 1
}

-- EDIT --

Because you said, "while loop is preferable universal substitution for all cases more complicated than the simple example of C-like for-loop"... I feel the need to expand on my answer. I don't want to be responsible for a bunch of bad code...

In most cases, there is a simple for-in loop that can handle the situation:

    for item in array {
// do something with item
}

for (item1, item2) in zip(array, array[1 ..< array.count]) {
// do something with item1 and item2
}

for (index, item1) in array.enumerate() {
for item2 in array[index + 1 ..< array.count] {
// do soemthing with item1 and item2
}
}

For your last case, you might be justified using a for look, but that is an extremely rare edge case.

Don't litter your code with for loops.

Fix warning C-style for Statement is deprecated in Swift 3

C-style for loop has been deprecated in Swift 3. You can continue using it for a while, but they will certainly disappear in the future.

You can rewrite your loop to Swift's style:

for i in 0..<len {
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}

Since you don't use i at all in the loop's body, you can replace it with:

for _ in 0..<len {
// do stuffs
}

Alternative for Swift C-style loop when iterator was changed conditionally within the loop

The iterator variable declared in a for loop is scoped to a single pass through that loop, so if you want to change it across multiple passes through the loop you'll need to use a while loop instead.

Also, since your intention seems to be "increment the loop counter only if checkCondition() is false" you can do that more clearly with a single, conditional increment, instead of using a decrement to undo your increment. Here are a couple of examples of that:

var i = 1
while i <= 10 {
if !checkCondition() {
i += 1
}
}

var j = 1
while j <= 10 {
j = checkCondition() ? j : j + 1
}

And a one that's maybe a little silly, but might come in handy if you do this sort of thing a lot:

extension IntegerType {
mutating func incrementIf(@autoclosure condition: () -> Bool) {
if condition() {
self = self + 1
}
}
}
var k = 1
while k <= 10 {
k.incrementIf(!checkCondition())
}

Of course, there's the further question of whether you want to be following this counter-based pattern at all (as @Sulthan notes in comments). Part of why Swift is doing away with the C-style for loop is that many loops with a counter are actually using that counter to index a collection, which is a pattern better served by collection iteration. So you might instead do something like:

for item in collection {
process(item)
if item.needsMoreProcessing {
process(item) // some more
}
}

for item in collection {
while item.needsProcessing {
process(item)
}
}

If something like this is what your loop is actually doing, writing it this way makes your purpose much more clear to other readers of your code (including your future self).

How to replace a complicated C-style for loop in Swift 2.2

The simplest solution is to just use a while loop:

Replace this code:

if bitsToWalk > 0 {
// Walk significant bits by shifting right until all bits are equal to 0.
for var bitsLeft = bitsToWalk; bitsLeft > 0; bitsLeft >>= 1 {
significantBitCount += 1
}
}

With the following while loop:

while bitsToWalk > 0 {
significantBitCount += 1
bitsToWalk >>= 1
}

Replace c style for-loop in Swift 2.2.1

Try this:

var i = column - 1
while i >= 0 && burgers[i, row]?.burgerType == burgerType {
i -= 1
horzLength += 1
}

This sort of abuse of the for loop syntax was the exact reason it was deprecated in Swift 2.2. Even if a for syntax was available, this would still be more clear than that abomination

What are the advantages Swift deprecates C-style for statement?

For details, see Swift Evolution - Remove C style for-loops

To quote the reasoning:

  1. Both for-in and stride provide equivalent behavior using Swift-coherent approaches without being tied to legacy terminology.
  2. There is a distinct expressive disadvantage in using for-loops compared to for-in in succinctness
  3. for-loop implementations do not lend themselves to use with collections and other core Swift types.
  4. The for-loop encourages use of unary incrementors and decrementors, which will be soon removed from the language.
  5. The semi-colon delimited declaration offers a steep learning curve from users arriving from non C-like languages
  6. If the for-loop did not exist, I doubt it would be considered for inclusion in Swift 3.

In summary: there are better ways (more expressive) than a C-style for-loop to iterate in Swift.

Some examples:

for-in over a range:

for i in 0 ..< 10 {
//iterate over 0..9
print("Index: \(i)")
}

for i in (0 ..< 10).reverse() {
//iterate over 9..0
print("Index: \(i)")
}

For arrays (and other sequences) we have many options (the following is not a complete list):

let array = ["item1", "item2", "item3"]

array.forEach {
// iterate over items
print("Item: \($0)")
}

array.reverse().forEach {
// iterate over items in reverse order
print("Item: \($0)")
}

array.enumerate().forEach {
// iterate over items with indices
print("Item: \($1) at index \($0)")
}

array.enumerate().reverse().forEach {
// iterate over items with indices in reverse order
print("Item: \($1) at index \($0)")
}

for index in array.indices {
// iterate using a list of indices
let item = array[index]
print("Item \(item) at index: \(index)")
}

Also note that if you are converting an array to another array, almost always you want to use array.filter or array.map or a combination of them.

For all Strideable types we can use the stride method to generate indices, for example:

for index in 10.stride(to: 30, by: 5) {
// 10, 15, 20, 25 (not 30)
print("Index: \(index)")
}

for index in 10.stride(through: 30, by: 5) {
// 10, 15, 20, 25, 30
print("Index: \(index)")
}

With arrays we can do:

for index in 0.stride(to: array.count, by: 2) {
// prints only every second item
let item = array[index]
print("Item \(item) at index: \(index)")
}

#warning: C-style for statement is deprecated and will be removed in a future version of Swift

Removing for init; comparison; increment {} and also remove ++ and -- easily. and use Swift's pretty for-in loop

   // WARNING: C-style for statement is deprecated and will be removed in a future version of Swift
for var i = 1; i <= 10; i += 1 {
print("I'm number \(i)")
}

Swift 2.2:

   // new swift style works well
for i in 1...10 {
print("I'm number \(i)")
}

For decrement index

  for index in 10.stride(to: 0, by: -1) {
print(index)
}

Or you can use reverse() like

  for index in (0 ..< 10).reverse() { ... }

for float type (there is no need to define any types to index)

 for index in 0.stride(to: 0.6, by: 0.1) {
print(index) //0.0 ,0.1, 0.2,0.3,0.4,0.5
}

Swift 3.0:

From Swift3.0, The stride(to:by:) method on Strideable has been replaced with a free function, stride(from:to:by:)

for i in stride(from: 0, to: 10, by: 1){
print(i)
}

For decrement index in Swift 3.0, you can use reversed()

for i in (0 ..< 5).reversed() {
print(i) // 4,3,2,1,0
}

Sample Image


Other then for each and stride(), you can use While Loops

var i = 0
while i < 10 {
i += 1
print(i)
}

Repeat-While Loop:

var a = 0
repeat {
a += 1
print(a)
} while a < 10

check out Control flows in The Swift Programming Language Guide

Replacement for C-style loop in Swift 2.2

Although it's not as "pretty", you can use stride:

for var i in 0.stride(to: -1, by: -1) {
print(i)
}

Converting a C-style for loop that uses division for the step to Swift 3

MartinR's solution is very generic and useful and should be part of your toolbox.

Another approach is to rephrase what you want: the powers of two from 7 down to 0.

for i in (0...7).reversed().map({ 1 << $0 }) {
print(i)
}


Related Topics



Leave a reply



Submit