Swift辞書にキーが含まれているかどうかを判別し、その値のいずれかを取得する


260

私は現在、次の(不器用な)コードを使用して、(空でない)Swift辞書に特定のキーが含まれているかどうかを判別し、同じ辞書から1つの(任意の)値を取得しています。

これをSwiftでよりエレガントにするにはどうすればよいですか?

// excerpt from method that determines if dict contains key
if let _ = dict[key] {
    return true
}
else {
    return false
}

// excerpt from method that obtains first value from dict
for (_, value) in dict {
    return value
}

indexForKeyより明確でより明確な場合は使用できます。stackoverflow.com/a/29299943/294884
Fattie

たいていの場合、基本的には次cityName:String = dict["city"] ?? "" のようになります 。?? ""ここでは、基本的に「そのようなキーがない場合は空白を返す」という意味です。
Fattie

回答:


481

あなたは必要としない任意のそれは辞書が既に何なので、これを行うための特別なコードを。フェッチdict[key]すると、ディクショナリにキーが含まれているかどうかがわかります。これは、取得するオプションがnil含まれていない(そして値が含まれている)ためです。

あなたがあれば、ちょうど辞書はキーが含まれているかどうかの質問に答えるためにしたい、頼みます:

let keyExists = dict[key] != nil

値が必要で、辞書にキーが含まれていることがわかっている場合は、次のように言います。

let val = dict[key]!

しかし、通常のように、キーが含まれていることがわからない場合-キーをフェッチして使用したいのですが、それが存在する場合のみ-次のようなものを使用しますif let

if let val = dict[key] {
    // now val is not nil and the Optional has been unwrapped, so use it
}

6
私はついていません。値を取得しました(2回)。これ以上何が欲しいですか?
マット2015年

「最初の値」というものはありません。辞書は順不同です。キーなしで値だけが必要な場合は、と言いdict.valuesます。
マット

1
dict.values不透明ですのでご注意ください。あなたはそれを循環することができますが、それだけです。(それはすべてではありませんが、私をユーモアに入れてください。)配列に具体化したい場合は、を使用してくださいdict.values.array
マット

1
@bubakazoubaこれを試してください:let d = ["hey":"ho"]; let s = d["hey"]; print(s)いつものように、これはオプションです。
マット

1
@クロスこれは非常に深い質問ですが、個別に質問してください。
マット

68

なぜ単にチェックしないのdict.keys.contains(key)ですか?dict[key] != nil値がnilの場合、チェックは機能しません。[String: String?]たとえば、辞書と同じです。


2
または、単に書く代わりに、この場合にif let val = dict[key]使用できますif let val = dict[key] as? String
Okhan Okbay 2017年

.keys.containsは、キーが存在するかどうか、または値がnilかどうかを区別するのに役立ちません。たぶん以前の迅速なバージョンで?SWIFT 4.に私のために動作しません
ローワンGontierの

8
これは非常に無駄になる可能性があります。(1)呼び出しdict.keysてすべてのキーを持つ配列を作成し、(2)すべてのキーを順番にチェックして1つ(または何も見つからない!)を見つけるからです。私はあなたがのケースに対処しようとしていることを理解していますが[String: String?]、その解決策には非常に注意してください...
charles

3
@charlesが述べたように、これは辞書を使用することで得られる高速ルックアップの利点を排除するので、私はこれに対して助言しますが、それでも間違いなく有効なオプションです。
businesscasual

4
あなたは必要があります決して直接辞書アクセスの複雑さはO(n)の代わりに、理論的な(ハッシュ関数の実装に依存)O(1)を持っている中で、このメソッドを使用していません。
クリプト

45

let keyExists = dict[key] != nil辞書にキーが含まれているが値がnilの場合、受け入れられた回答は機能しません。

辞書にキーがまったく含まれていないことを確認したい場合は、これを使用してください(Swift 4でテスト済み)。

if dict.keys.contains(key) {
  // contains key
} else { 
  // does not contain key
}

3
これは漢の答えと同じです。
Declan McKenna

1
== nil辞書にオプションの値がある場合でも、チェックは機能します。これは、検索結果がとしてラップされるためOptionalです。一方、ルックアップされた値が実際にnil存在するかどうかを確認するには、を使用できます== .some(nil)
jedwidz 2018年

1
他のメソッドのO(1)ルックアップと比較して、このメソッドを使用する効率を追加します。それはO(n)ルックアップだと思います
アルベルトベガ

1
@ AlbertoVega-MSFTですO(1)。次も参照してください:github.com/apple/swift-evolution/blob/master/proposals/…どうしてそれがO(n)何だと思ったのですか?
アレクサンダー-モニカを復活

1
ここでのDictionary.Keys.contains(...)関数のドキュメンテーションは、それが複雑であると述べています。O(n)n
Adil Hussain

5

@mattから必要なものを取得したように見えますが、キーの値を取得する簡単な方法が必要な場合、またはそのキーが存在しない場合は最初の値のみを取得する場合は、次のようにします。

extension Dictionary {
    func keyedOrFirstValue(key: Key) -> Value? {
        // if key not found, replace the nil with 
        // the first element of the values collection
        return self[key] ?? first(self.values)
        // note, this is still an optional (because the
        // dictionary could be empty)
    }
}

let d = ["one":"red", "two":"blue"]

d.keyedOrFirstValue("one")  // {Some "red"}
d.keyedOrFirstValue("two")  // {Some "blue"}
d.keyedOrFirstValue("three")  // {Some "red”}

最初の値として実際に何が得られるかを保証するものではないことに注意してください。この場合は「赤」を返すだけです。


1
??演算子を上手に使用することで、私の便利な解決策が得られましたが、拡張機能として、デフォルト値はデータの不確実性や予期しない動作を示す可能性があります。それDictionaryは採用すべき具体的なサブクラスのように聞こえます。nilシチュエーション固有の機能を除いたリターンの場合、どのくらいの頻度で最初の値が必要ですか
NoodleOfDeath


0

オプションのNSAttributedStringを格納するキャッシュ実装の私のソリューション:

public static var attributedMessageTextCache    = [String: NSAttributedString?]()

    if attributedMessageTextCache.index(forKey: "key") != nil
    {
        if let attributedMessageText = TextChatCache.attributedMessageTextCache["key"]
        {
            return attributedMessageText
        }
        return nil
    }

    TextChatCache.attributedMessageTextCache["key"] = .some(.none)
    return nil

0

これがSwift 3で私のために働くものです

let _ = (dict[key].map { $0 as? String } ?? "")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.