Is there a way to work with reverse ranges in Swift?
For example:
for i in 5...1 {
// do something
}
is an infinite loop.
In newer versions of Swift that code compiles, but at runtime gives the error:
Fatal error: Can't form Range with upperBound < lowerBound
I know I can use 1..5 instead, calculate j = 6 - i and use j as my index. I was just wondering if there was anything more legible?
Update For latest Swift 3 (still works in Swift 4)
You can use the reversed() method on a range
for i in (1...5).reversed() { print(i) } // 5 4 3 2 1
Or stride(from:through:by:) method
for i in stride(from:5,through:1,by:-1) { print(i) } // 5 4 3 2 1
stride(from:to:by:) is similar but excludes the last value
for i in stride(from:5,to:0,by:-1) { print(i) } // 5 4 3 2 1
Update For latest Swift 2
First of all, protocol extensions change how reverse is used:
for i in (1...5).reverse() { print(i) } // 5 4 3 2 1
Stride has been reworked in Xcode 7 Beta 6. The new usage is:
for i in 0.stride(to: -8, by: -2) { print(i) } // 0 -2 -4 -6
for i in 0.stride(through: -8, by: -2) { print(i) } // 0 -2 -4 -6 -8
It also works for Doubles:
for i in 0.5.stride(to:-0.1, by: -0.1) { print(i) }
Be wary of floating point compares here for the bounds.
Earlier edit for Swift 1.2: As of Xcode 6 Beta 4, by and ReverseRange don't exist anymore :[
If you are just looking to reverse a range, the reverse function is all you need:
for i in reverse(1...5) { println(i) } // prints 5,4,3,2,1
As posted by 0x7fffffff there is a new stride construct which can be used to iterate and increment by arbitrary integers. Apple also stated that floating point support is coming.
Sourced from his answer:
for x in stride(from: 0, through: -8, by: -2) {
println(x) // 0, -2, -4, -6, -8
}
for x in stride(from: 6, to: -2, by: -4) {
println(x) // 6, 2
}
There's something troubling about the asymmetry of this:
for i in (1..<5).reverse()
...as opposed to this:
for i in 1..<5 {
It means that every time I want to do a reverse range, I have to remember to put the parentheses, plus I have to write that .reverse() on the end, sticking out like a sore thumb. This is really ugly in comparison to C-style for loops, which are symmetrical counting up and counting down. So I tended to use C-style for loops instead. But in Swift 2.2, C-style for loops are going away! So I've had to scurry around replacing all my decrementing C-style for loops with this ugly .reverse() construct — wondering all the while, why on earth isn't there a reverse-range operator?
But wait! This is Swift — we're allowed to define our own operators!! Here we go:
infix operator >>> {
associativity none
precedence 135
}
func >>> <Pos : ForwardIndexType where Pos : Comparable>(end:Pos, start:Pos)
-> ReverseRandomAccessCollection<(Range<Pos>)> {
return (start..<end).reverse()
}
So now I'm allowed to say:
for i in 5>>>1 {print(i)} // 4, 3, 2, 1
This covers just the most common case that occurs in my code, but it is far and away the most common case, so it's all I need at present.
I had a kind of internal crisis coming up with the operator. I would have liked to use >.., as being the reverse of ..<, but that's not legal: you can't use a dot after a non-dot, it appears. I considered ..> but decided it was too hard to distinguish from ..<. The nice thing about >>> is that it screams at you: "down to!" (Of course you're free to come up with another operator. But my advice is: for super symmetry, define <<< to do what ..< does, and now you've got <<< and >>> which are symmetrical and easy to type.)
Swift 3 version (Xcode 8 seed 6):
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound) ->
ReversedRandomAccessCollection<CountableRange<Bound>>
where Bound : Comparable, Bound.Stride : Integer {
return (minimum..<maximum).reversed()
}
Swift 4 version (Xcode 9 beta 3):
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedRandomAccessCollection<CountableRange<Bound>>
where Bound : Comparable & Strideable {
return (minimum..<maximum).reversed()
}
Swift 4.2 version (Xcode 10 beta 1):
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedRandomAccessCollection<Range<Bound>>
where Bound : Strideable {
return (minimum..<maximum).reversed()
}
Swift 5 version (Xcode 10.2.1):
infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
-> ReversedCollection<Range<Bound>>
where Bound : Strideable {
return (minimum..<maximum).reversed()
}
It appears that the answers to this question have changed a bit as we've progressed through the betas. As of beta 4, both the by() function and the ReversedRange type have been removed from the language. If you're looking to make a reversed range, your options are now as follows:
1: Create a forward range, and then use the reverse() function to reverse it.
for x in reverse(0 ... 4) {
println(x) // 4, 3, 2, 1, 0
}
for x in reverse(0 ..< 4) {
println(x) // 3, 2, 1, 0
}
2: Use the new stride() functions that were added in beta 4, which includes functions to specify the starting and ending indexes, as well as the amount to iterate by.
for x in stride(from: 0, through: -8, by: -2) {
println(x) // 0, -2, -4, -6, -8
}
for x in stride(from: 6, to: -2, by: -4) {
println(x) // 6, 2
}
Note that I've also included the new exclusive range operator in this post as well. .. was replaced with ..<.
Edit: From the Xcode 6 beta 5 release notes, Apple added the following suggestion for handling this:
ReverseRange has been removed; use lazy(x..
Here's an example.
for i in lazy(0...5).reverse() {
// 0, 1, 2, 3, 4, 5
}
Xcode 7, beta 2 (< Swift 3.0):
for i in (1...5).reverse() {
// do something
}
Update for Xcode 8.0+ (Swift 3.0+), per Developer Documentation, available as of 8 Dec 2020:
To iterate through a collection in reverse, without changing the collection's contents, use reversed -
let word = "Backwards"
for char in word.reversed() {
print(char, terminator: "")
}
// Prints "sdrawkcaB"
In this case, a wrapper around the collection reads the collection's contents and returns them in reverse order.
To reverse the collection's contents, use a type initializer, and provide it the collection reversed. This makes a new collection with the same contents, but reversed:
let reversedWord = String(word.reversed())
print(reversedWord)
// Prints "sdrawkcaB"
Additionally, you can use the generic function stride(from:to:by:) to return the collection's contents in reverse (as well as in its normal order):
for countdown in stride(from: 3, to: 0, by: -1) {
print("\(countdown)...")
}
// 3...
// 2...
// 1...
If the from value is higher than the to value, and the by value is negative, stride reads contents in reverse.
If the from value is lower than the to value, and the by value is positive, stride will read through the contents in their original order.
Note: Collections include arrays, sets, dictionaries, as well as other specialized collections. As long as the collection is iterable, these techniques will work.
2nd Note: as of 8 Dec 2020, Swift versions and their associated Xcode versions can be found at https://swiftly.dev/swift-versions. According to this reference, Xcode 8.0+ is associated with Swift 3.0, which is when reverse() became reversed().
Swift 3, 4+: you can do it like this:
for i in sequence(first: 10, next: {$0 - 1}) {
guard i >= 0 else {
break
}
print(i)
}
result: 10, 9, 8 ... 0
You can customise it any way you like. For more info read func sequence<T> reference
This could be another way of doing this.
(1...5).reversed().forEach { print($0) }
Reverse() function is used for reverse number.
Var n:Int // Enter number
For i in 1...n.reverse()
{
Print(i)
}
Related
When I want to pass through and remove an item or items from an array (when certain conditions are met), I typically iterate backward in the C-style for-loop and remove the item by index, avoiding the problem of index numbers being changed of the next item to be processed, or the changing size of the list affecting how many times the loop is passed through. But the C for-loop has been removed in Swift 3.
Here is my Swift 2.3 code for the initialization of the loop:
for (var i = allowedItems.count - 1; i > -1; i -= 1)
Here is the monstrosity created by the Swift 3 converter:
for (i in ((-1 + 1)...allowedItems.count - 1).reversed())
This version does not compile however. ("Expected ',' separator" at the "in" operator).
I simplify the "-1 + 1" bit to zero:
for (i in (0...allowedItems.count - 1).reversed())
Now the error is "Expected Sequence expression for for-each loop".
What is the safe and hopefully reasonably elegant way of iterating backward in Swift 3, in which an index or counter variable is made available for use in specifying which item should be removed? This type of logic appears a number of places in my code so I want to make sure to find the best solution.
Thanks.
What is the safe and hopefully reasonably elegant way of iterating backward in Swift 3
The built-in way is:
for i in (0 ..< allowedItems.count).reversed()
The elegant way is:
for i in allowedItems.count >>> 0
(where >>> is the custom operator that I define here).
Use stride:
for i in stride(from: allowedItems.count - 1, through: 0, by: -1) {
}
What is the safe and hopefully reasonably elegant way of iterating
backward in Swift 3, in which an index or counter variable is made
available for use in specifying which item should be removed?
This doesn't answer the technical question, but possibly the underlying XY problem: have you considered simply filtering your array based on the criteria "when certain conditions are met"?
func certainConditionsForKeepingAreMet(_ element: YourElementType) -> Bool { /* ... */ }
allowedItems = allowedItems.filter(certainConditionsForKeepingAreMet)
E.g.
var allowedItems = [1, 3 ,6, 2]
func certainConditionsForKeepingAreMet(_ element: Int) -> Bool { return element < 3 }
allowedItems = allowedItems.filter(certainConditionsForKeepingAreMet)
print(allowedItems) // [1, 2]
If you'd like to remove and use the removed elements (on-the-fly), you could simply pipe the elements that are to be removed to some "use this element" function, in the course of checking the conditions for the elements.
func doSomethingWith(_ element: Int) { print("Removed", element) }
func certainConditionsForKeepingAreMet(_ element: Int) -> Bool {
if element >= 3 {
doSomethingWith(element)
return false
}
return true
}
var allowedItems = [1, 3 ,6, 2]
allowedItems = allowedItems.filter(certainConditionsForKeepingAreMet)
/* Removed 3
Removed 6 */
print(allowedItems) // [1, 2]
I'm new to Swift and I was trying to make something which coverts any base 10 number to a different base. I started by making a function which finds the the greatest exponent value for a base and a number. For example, if the number was 26 and the base was 5, the greatest exponent would be 2. I created the program but it always gives me an error. I feel like it might have something to do with the Double(num/exponentedBase), but I'm not sure. Finally, is there a better way to do this. Please help.
The xor operator in the first line in combination with the division in the second line of your functions is causing the exception.
The xor operator returns a new number whose bits are set to 1 where the input bits are different and are set to 0 where the input bits are the same (see https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html, chapter Bitwise XOR operator).
Therefor your variable "exponentedbase" can be 0 and it is possible that you are trying to divide through 0, which causes the exception.
When you print the values of your greatestCommonExponent function with num 12 and base 2, you get the following result:
first call:
num: 12
base: 2
exponent: 1
exponentedbase: 3
second call:
num: 12
base: 2
exponent: 2
exponentedbase: 0
You should add a guard statement to make your code save. (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID120, chapter "early exit")
Edit:
The ^ operator in Swift is the XOR function. The statement 2^2 will compare the numbers bitwise.
10 XOR 10 = 00
For further reference follow https://en.wikipedia.org/wiki/Exclusive_or or https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html
If you want to have a pow function, you should do something like this:
How to get the Power of some Integer in Swift language?
This should work for you:
func greatestCommonExponent(num: Int, base: Int, exponent: Int = 1) -> Int {
let exponentedbase = base^^exponent
let value = Double(num/exponentedbase)
if value > 1 {
return greatestCommonExponent(num: num, base: base, exponent: exponent+1)
}
if value == 1 {
return exponent
} else {
return exponent-1
}
}
precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(Double(radix), Double(power)))
}
greatestCommonExponent(num: 12, base: 2)
The result of 12 base 2 is 3
With the removal of the traditional C-style for-loop in Swift 3.0, how can I do the following?
for (i = 1; i < max; i+=2) {
// Do something
}
In Python, the for-in control flow statement has an optional step value:
for i in range(1, max, 2):
# Do something
But the Swift range operator appears to have no equivalent:
for i in 1..<max {
// Do something
}
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
}
I'm new to Swift and is trying to learn the concept of extension. I saw this code in "the swift programming language", which tries to return the decimal digit 'n' places in from the right of the number. The code work fine, but I am struggling to understand how the code actually works.
Could someone explain it to me?
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7
746381295[9]
Extensions work by adding capability to existing types, with the caveat that they cannot introduce their own storage. In the case in point:
/*1*/ extension Int {
/*2*/ subscript(var digitIndex: Int) -> Int {
/*3*/ var decimalBase = 1
/*4*/ while digitIndex > 0 {
/*5*/ decimalBase *= 10
/*6*/ --digitIndex
/*7*/ }
/*8*/ return (self / decimalBase) % 10
}
}
Line 1 defines the extension as applying to all Int types.
Line 2 is setting up a new subscript operator for an Int, which will allow you to have 12345[4] and produce 'something'. Lines 3-8 define that something.
The while in lines 4-8 is multiplying decimalBase by 10 for 'digitIndex' times. A bit of a weird way of doing it, but never mind. The upshot is if digitIndex is 1, decimalBase is 10; if it's 2, decimal base is 100; 3 it's 1000; etc.
The guts is in line 8. First it retrieves self. Since the extension applies to an Int, self will be that integer value. It then divides it by decimalBase, and because they're both integers, any fractional part will be lost. Therefore in the case of 746381295[2] decimalBase will be 100 so you get 7463812. Then it uses '%' to get the remainder of the division by 10. So 7463812 divided by 10 is 746381 with a remainder of 2. So the returned value is 2.
Hope that explains it.
Pre-empting your question, I might use for in this case, instead of the while:
for _ in 0..<digitIndex {
decimalBase *= 10
}
I haven't thought too much about how often the above loops, it might run once to often or once too few, but you get the idea.
Even better would be to use the 'raising to the power' operator (not really sure what it's called).
decimalBase = 10 ^^ digitIndex
Then the whole definition could boil down to:
return (self / (10 ^^ digitIndex)) % 10
I will leave it to you to decide whether that's better or not.
Either way, I wouldn't really create this extension, and I assume it was just done for the purpose of demonstration.
Simply put, decimalBase is calculated to be 1 with an index of 0, 10 with an index of 1, 100 with an index of 2, 1,000 with an index of 3, and so on. In other words, decimalBase ends up equal to 10 ^ digitIndex.
So look at the case where digitIndex is 3, for instance. decimalBase will end up being 1,000, so:
746381259 / 1000 == 746381
and then:
746381 % 10 == 1
so that's how you get from 746381259[3] to 1.
I'm in the process of getting comfortable passing unnamed functions as arguments and I am using this to practice with, based off of the examples in the Swift Programming Guide.
So we have an array of Ints:
var numbers: Int[] = [1, 2, 3, 4, 5, 6, 7]
And I apply a transform like so: (7)
func transformNumber(number: Int) -> Int {
let result = number * 3
return result
}
numbers = numbers.map(transformNumber)
Which is equal to: (7)
numbers = numbers.map({(number: Int) -> Int in
let result = number * 3
return result;
})
Which is equal to: (8)
numbers = numbers.map({number in number * 3})
Which is equal to: (8)
numbers = numbers.map({$0 * 3})
Which is equal to: (8)
numbers = numbers.map() {$0 * 3}
As you can see in the following graphic, the iteration count in the playground sidebar shows that in the furthest abstraction of a function declaration, it has an 8 count.
Question
Why is it showing as 8 iterations for the last two examples?
It's not showing 8 iterations, really. It's showing that 8 things executed on that line. There were 7 executions as part of the map function, and an 8th to do the assignment back into the numbers variable.
It looks like this could probably provide more helpful diagnostics. I would highly encourage you to provide feedback via https://bugreport.apple.com.
Slightly rewriting your experiment to use only closures, the call counts still differ by one:
Case 1: Explicitly specifying argument types (visit count is 7)
var f1 = {(number: Int) -> Int in
let result = number * 3
return result
}
numbers.map(f1)
Case 2: Implicit argument types (visit count is 8)
var f2 = {$0 * 3}
numbers.map(f2)
If the (x times) count reported by the REPL does indeed represent a count of visits to that code location, and noting that the count is greater by one in cases where the closure type arguments are not explicitly specified (e.g. f2), my guess is that at least in the playground REPL, the extra visit is to establish actual parameter types and fill that gap in the underlying AST.