对于数组方法:
@inlinable public func index(_ i: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int?
文档给出了一个例子:
/// let numbers = [10, 20, 30, 40, 50]
/// if let i = numbers.index(numbers.startIndex,
/// offsetBy: 4,
/// limitedBy: numbers.endIndex) {
/// print(numbers[i])
/// }
为什么它使用 numbers.endIndex
作为limit
参数,这显然是错误的,我们应该使用 numbers.endIndex-1
,它在这里有效,因为distance
参数是 4,如果distance
是 5,它会崩溃。
我认为这是一个不好的例子,还是我错过了什么?
你是对的,该代码不能防止"索引超出范围"错误。 endIndex
数组(或通常集合(的"过尾"位置:它是一个有效的索引,但是一个无效的下标。
对于非负偏移,
if let i = numbers.index(numbers.startIndex,
offsetBy: offset,
limitedBy: numbers.endIndex), i != numbers.endIndex {
print(numbers[i])
}
将是一个安全的变体。对于数组,您还可以使用 numbers.endIndex-1
作为限制。但这不适用于任意集合,因为并非所有集合都按整数索引(String
就是一个很好的例子。
您也可以检查是否offset < numbers.count
,但请注意,访问任意集合的count
可以是 O(N( 操作。
另一个变体是
if let num = numbers.dropFirst(offset).first {
print(num)
}
适用于任意集合。与前面的示例一样,必须单独排除可能的负偏移。
您也可以使用
if numbers.indices.contains(index) {
print(numbers[index])
}
为了安全起见,下标。如果您记住集合索引不一定是从零开始,也不一定是从整数开始,则这适用于任意集合。