我对快速误导性文档的看法是错误的吗?



对于数组方法:

@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])
}

为了安全起见,下标。如果您记住集合索引不一定是从零开始,也不一定是从整数开始,则这适用于任意集合。

最新更新