对于Array方法:
@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,则会崩溃。
我认为这是一个不好的例子,还是我错过了什么?
答案 0 :(得分:2)
您是对的,该代码无法防止出现“索引超出范围”错误。 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])
}
为了安全起见。如果您记住集合索引不一定是从零开始的,并且不一定是整数,那么这对任意集合都有效。