1. ホーム
  2. xcode

[解決済み】Swiftで安全な(境界がチェックされた)配列検索、オプションのバインディングを通して?

2022-03-28 20:06:26

質問

Swiftで配列を持っていて、境界外のインデックスにアクセスしようとすると、当然のことながらランタイムエラーが発生します。

var str = ["Apple", "Banana", "Coconut"]

str[0] // "Apple"
str[3] // EXC_BAD_INSTRUCTION

しかし、私は、すべてのオプションのチェーンと 安全性 のようなことをするのは簡単でしょう。

let theIndex = 3
if let nonexistent = str[theIndex] { // Bounds check + Lookup
    print(nonexistent)
    ...do other things with nonexistent...
}

の代わりに

let theIndex = 3
if (theIndex < str.count) {         // Bounds check
    let nonexistent = str[theIndex] // Lookup
    print(nonexistent)   
    ...do other things with nonexistent... 
}

しかし、これでは、オールドの if ステートメントでチェックし、インデックスが str.count .

を自分で追加してみました。 subscript() の実装がありますが、元の実装に呼び出しを渡す方法や、添え字記法を使わずにアイテムにアクセスする方法(インデックスベース)がよく分かりません。

extension Array {
    subscript(var index: Int) -> AnyObject? {
        if index >= self.count {
            NSLog("Womp!")
            return nil
        }
        return ... // What?
    }
}

解決方法は?

アレックスの回答 は良いアドバイスと解決策を提供してくれますが、私は偶然にもこの機能を実装するもっと良い方法を見つけました。

Swift 3.2 以降

extension Collection {

    /// Returns the element at the specified index if it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

Swift 3.0と3.1

extension Collection where Indices.Iterator.Element == Index {

    /// Returns the element at the specified index if it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Generator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

を思いついたHamishの功績は大きい。 Swift 3 のためのソリューション .


使用例

let array = [1, 2, 3]

for index in -20...20 {
    if let item = array[safe: index] {
        print(item)
    }
}