49582


表題の通りです。以下のようなイメージで考えていました。

[code]

    let rank = [
        0...1: "rank1",
        2...3: "rank2",
        4...5: "rank3",
        6...34: "rank4",
        35...77: "rank5"]
    print(rank[0])     // "rank1"
    print(rank[11])    // "rank4"
    
[/code]

Xcodeでは宣言は出来ましたが、呼び出しで下記のようなエラーが出てビルド出来ませんでした。

[code]

    Cannot subscript a value of type '[ClosedRange<Int> : String]' with an index of type 'Int'
    
[/code]

おそらくKeyに設定したRangeそのものがそのままKeyに設定されてしまったものと思います。

[code]

    rank[0]
    
[/code]

のように呼び出す実装が実現可能な方法をご存知の方いらっしゃいましたらご回答お願いいたします。


CC BY-SA 4.0
2018-10-23T11:52:36.017
49570
2018-10-23T14:34:02.893
30511
question
swift swift4
DictionaryのKeyにRangeを設定する方法


いろいろやり方は考えられるでしょうが、

  * 実行効率は気にしない
  * 読み出し専用

と言うことであれば、こんなextensionを定義することができます。

[code]

    extension Dictionary {
        subscript<T>(key: T) -> Value? where Key == ClosedRange<T> {
            for (range, value) in self {
                if range.contains(key) {
                    return value
                }
            }
            return nil
        }
    }
    
[/code]

`subscript`と言うのはSwiftで`[`
`]`による値の呼び出しを定義するときのやり方。`Dictionary`型にはすでにいくつかの`subscript`が定義されていますが、`Dictionary.Key`型が`ClosedRange<T>`型の場合にだけ有効になります。ちなみに`T`は`ClosedRange<T>`を作れるような型であれば`Int`以外でもOK。

後はご質問文内にあるように使えます。

[code]

    let rank = [
        0...1: "rank1",
        2...3: "rank2",
        4...5: "rank3",
        6...34: "rank4",
        35...77: "rank5"]
    print(rank[0])     //->Optional("rank1")
    print(rank[11])    //->Optional("rank4")
    
[/code]

値が`Optional`型になるのは、`Dictionary`から普通に値を取り出すときと同じと言うことで。

(上記のextensionの定義を変更してやれば、配列のように、該当する値がない場合にはfatalErrorとする代わり、非Optionalな値を返すように変更することもできます。)

お試し下さい。


CC BY-SA 4.0
2018-10-23T14:34:02.893
49582
2018-10-23T14:34:02.893
13972
49570
answer