Why is my Swift loop failing with error “Can't form range with end < start”?

后端 未结 6 1628
北海茫月
北海茫月 2021-02-05 01:44

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 wil

相关标签:
6条回答
  • 2021-02-05 02:03

    If you want to use range where upperBound < lowerBound, you can add reversed() to it.

    for eg: for number in (0...highestPossibleNumber).reversed()

    0 讨论(0)
  • 2021-02-05 02:05

    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:)

    0 讨论(0)
  • 2021-02-05 02:08

    Swift 5

    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:

    • http://michael-brown.net/2016/using-stride-to-convert-c-style-for-loops-to-swift-2.2/
    • http://swiftdoc.org/v2.1/protocol/Strideable/
    0 讨论(0)
  • 2021-02-05 02:11

    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"
    
    0 讨论(0)
  • 2021-02-05 02:16

    In your second loop, i will always start at 2, which means you're looping from 2...1

    0 讨论(0)
  • 2021-02-05 02:17

    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"]
    
    0 讨论(0)
提交回复
热议问题