Swift 2.2 decrementing specific for loop in Swift 3
Your code isn't counting the number of 3-letter words in the array. It is counting the number of 3-letter words at the end of the array. It will return 0
for your sample input array.
When a C-style for loop is very complex, the final fallback solution is to translate it to a while loop. Any C-style for loop can be mechanically converted into an equivalent while loop, which means you can do it even if you don't fully understand what it is doing.
This for loop:
for initialization; condition; increment {
// body
}
is equivalent to:
initialization
while condition {
// body
increment
}
So, your code is equivalent to:
let array = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]
var threeLetterWords = 0
var i = array.count - 1
while i >= 0 && array[i]?.characters.count == 3 {
i -= 1
threeLetterWords += 1
}
print("Found words: \(threeLetterWords)") // says `Found words: 0`
Here is how to use a for loop and guard to do the equivalent of your code:
let array = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]
var num3LetterWords = 0
for word in array.reversed() {
guard word?.characters.count == 3 else { break }
num3LetterWords += 1
}
print(num3LetterWords)
How to iterate for loop in reverse order in swift?
Xcode 6 beta 4 added two functions to iterate on ranges with a step other than one:stride(from: to: by:)
, which is used with exclusive ranges and stride(from: through: by:)
, which is used with inclusive ranges.
To iterate on a range in reverse order, they can be used as below:
for index in stride(from: 5, to: 1, by: -1) {
print(index)
}
//prints 5, 4, 3, 2
for index in stride(from: 5, through: 1, by: -1) {
print(index)
}
//prints 5, 4, 3, 2, 1
Note that neither of those is a Range
member function. They are global functions that return either a StrideTo
or a StrideThrough
struct, which are defined differently from the Range
struct.
A previous version of this answer used the by()
member function of the Range
struct, which was removed in beta 4. If you want to see how that worked, check the edit history.
Decrement index in a loop after Swift C-style loops deprecated
Here is an easier (and more Swifty) approach.
for i in (0 ..< 5).reversed() {
print(i) // 4,3,2,1,0
}
let array = ["a", "b", "c", "d", "e"]
for element in array.reversed() {
print(element) // e,d,c,b,a
}
array.reversed().forEach { print($0) } // e,d,c,b,a
print(Array(array.reversed())) // e,d,c,b,a
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)
}
How can I do a Swift for-in loop with a step?
The Swift synonym for a "step" is "stride" - the Strideable protocol in fact, implemented by many common numerical types.
The equivalent of (i = 1; i < max; i+=2)
is:
for i in stride(from: 1, to: max, by: 2) {
// Do something
}
Alternatively, to get the equivalent of i<=max
, use the through
variant:
for i in stride(from: 1, through: max, by: 2) {
// Do something
}
Note that stride
returns a StrideTo
/StrideThrough
, which conforms to Sequence
, so anything you can do with a sequence, you can do with the result of a call to stride
(ie map
, forEach
, filter
, etc). For example:
stride(from: 1, to: max, by: 2).forEach { i in
// Do something
}
Can you tell a for-loop to conditionally advance by more than one step?
No, you can't change how a for-in
loop iterates from within the loop.
A while
loop with your own index counter is probably the simplest solution in this case. Though you may be able to make use of sequence(first:next:)
in a for-in
loop.
Related Topics
C++ Dylib in Swift Project - Undefined Symbols for Function Exposed in Dylib
Use Huge Numbers in Apple Swift
Swiftui How to Programatically Adjust Spacing Between Images and Text
How to Loop All Firebase Children at Once in the Same Loop
Raw Value of Enumeration, Default Value of a Class/Structure, What's the Different
How to Handle Two Possible Date Formats
Why Can't I Use 'Type' as the Name of an Enum Embedded in a Struct
Nsurl Fail Able Initialiser Initwithstring: Does Not Return Nil on Empty String in Swift
Swift Why Isn't My Date Object That's (Equatable) Equal After Converting It to a String and Back
Change Mkmarkerannotationview Size
When Two Optionals Are Assigned to an If Let Statement, Which One Gets Unwrapped? Swift Language
Swift How to Sort Dict Keys by Byte Value and Not Alphabetically
Using Tvposterimage in Tvuikit for Tvos 12
How to Pass a Local Function to Another Object During Init
Why Does the Completion Handler Does Not Return Anything