4

I have an array anArray and I want to create a sub array by specifying a range range, like:

 var range: Range<Int>
 guard let slice = anArray[range] else {
      return nil
 }

I run into a problem where the code throws an "Array index is out of range:" exception.

 var range: Range<Int>
 guard range.upperBound > anArray.count - 1 else {
        return nil
    }
 guard let slice = anArray[range] else {
      return nil
 }

But I see get the Array out of range exception. Can you please tell me what did I miss?

hap497
  • 154,439
  • 43
  • 83
  • 99

2 Answers2

4

Your operator is backwards, the guard should be ensuring

guard range.upperBound <= anArray.count - 1 else { ...

not >

(The guard will skip the else block if its condition is true - it isn't an if, it's an else).

Corbell
  • 1,283
  • 8
  • 15
1

Besides the fact that you were using the wrong operator beware that not all collections starts at zero and not all collections have all elements up to its index before the endIndex. Thats the case of the result of your subscription which returns an ArraySlice. You should always check the collection indices, not its count. Resuming you should check if your range fits within the collection indices. Check this post. Note that RandomAccessCollection's subscript does NOT return an optional, it would crash if you pass an invalid range.

guard range.clamped(to: anArray.indices) == range else {
    return nil
}

let slice = anArray[range]
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571