Reputation: 6537
I have a for loop that checks if a number is a factor of a number, then checks if that factor is prime, and then it adds it to an array. Depending on the original number, I will get an error saying
fatal error: Can't form range with end < start
This happens almost every time, but for some numbers it works fine. The only numbers I have found to work with it are 9, 15, and 25.
Here is the code:
let num = 16 // or any Int
var primes = [Int]()
for i in 2...(num/2) {
if ((num % i) == 0) {
var isPrimeFactor = true
for l in 2...i-1 {
if ((i%l) == 0) {
isPrimeFactor = false;
}//end if
}//end for
if (isPrimeFactor == true) {
primes.append(i)
}//end if
}//end if
}//end for
Upvotes: 44
Views: 43046
Reputation: 11
The easiest solution is to apply ".reversed()" to your array. Example: array.reversed()
Upvotes: 1
Reputation: 359
Using a simple solution you can make for loop reverse using Stride and -
func reverseArray(oldarray: [String]) -> [String] {
var newArray = [String]()
let len = oldarray.count
for i in stride(from: len - 1, through: 0, by: -1)
{ newArray.append(oldarray[i])
print(i)
}
return newArray
}
input : print(reverseArray(oldarray: ["World", "Hello"]))
output : ["Hello", "World"]
Upvotes: 0
Reputation: 2487
If you want to use range where upperBound < lowerBound, you can add reversed() to it.
for eg: for number in (0...highestPossibleNumber).reversed()
Upvotes: 2
Reputation: 8095
If you need a loop with dynamic value-range, I suggest that using stride(to:by:)
instead of ..<
or ...
Basically ..<
or ...
will be crashed if start_index > end_index
.
This will be crash:
let k = 5
for i in 10...k { print("i=\(i)") }
for i in 10..<k { print("i=\(i)") }
How to fix:
let k = 5
for i in stride(from: 10, through: k, by: 1) { print("i=\(i)") }
for i in stride(from: 10, to: k, by: 1) { print("i=\(i)") }
NOTE:
The code above won't print out anything, but it won't be crash when execution.
Also, if you want to stride from a higher number to a lower number then the by
parameter needs to be changed to a negative number.
Reference:
Upvotes: 76
Reputation: 877
Both ClosedRange
and CountableRange
throw this error unless start <= end
. One problem with using stride(from:to:by)
is that it returns a Strideable
and not a Range
, which doesn't work with the "is in range" operator ~=
. To handle these cases, I use an extension which gives me a bounds-safe range, where invalid ranges become an empty range:
extension Int {
func until(_ end: Int) -> CountableRange<Int> {
return self <= end ? self..<end : self..<self
}
func through(_ end: Int) -> CountableRange<Int> {
return self <= end ? self..<(end + 1) : self..<self
}
}
Both return CountableRange
so that an invalid through
range becomes an empty range. (Side note: the name until
is chosen because this "safe" range behaves the same as until
ranges in Kotlin/Android).
Usage:
for i in 0.until(3) { /* do something */ }
let printRange = { (range: Range<Int>) -> Void in
for i in range {
print(i, terminator: " ")
}
print()
}
printRange(0.until(3)) // prints "0 1 2"
printRange(0.until(0)) // prints ""
printRange(3.until(0)) // prints ""
printRange(0.through(3)) // prints "0 1 2 3"
printRange(0.through(0)) // prints "0"
printRange(3.through(0)) // prints ""
print(0.until(1) ~= -1) // prints "false"
print(0.until(1) ~= 0) // prints "true"
print(0.until(1) ~= 1) // prints "false"
print(0.until(0) ~= 0) // prints "false"
print(1.until(0) ~= 0) // prints "false"
print(0.through(1) ~= -1) // prints "false"
print(0.through(1) ~= 0) // prints "true"
print(0.through(1) ~= 1) // prints "true"
print(0.through(0) ~= 0) // prints "true"
print(1.through(0) ~= 0) // prints "false"
Upvotes: 5
Reputation: 1592
SWIIFT 4
The best way to go is to use stride as by this documentation page: Generic Function stride(from:to:by:)
for i in stride(from: 10, through: 5, by: -1) { print(i) }
and stride through if you want to include the lowerBound: Generic Function stride(from:through:by:)
Upvotes: 6
Reputation: 5006
In your second loop, i
will always start at 2, which means you're looping from 2...1
Upvotes: 9