2015-01-24 9 views
153

Ich verwende derzeit die folgenden (schwerfälligen) Codeabschnitte, um zu bestimmen, ob ein (nicht leeres) Swift-Wörterbuch einen bestimmten Schlüssel enthält und einen (beliebigen) Wert erhält aus dem gleichen Wörterbuch.Ermitteln, ob das Swift-Wörterbuch einen Schlüssel enthält und einen seiner Werte erhält

Wie kann man das in Swift eleganter machen?

// 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 
} 
+0

Sie können 'indexForKey' verwenden, wenn Sie das Gefühl haben, dass es klarer und expliziter ist; http://stackoverflow.com/a/29299943/294884 – Fattie

+0

Sehr oft, was Sie wollen, ist im Grunde: 'cityName: String = dict [" city "] ?? "" 'Das' ?? "" bedeutet hier grundsätzlich "wenn es keinen solchen Schlüssel gibt, gebe ein Leerzeichen zurück". – Fattie

Antwort

310

Sie brauchen nicht jeden speziellen Code, dies zu tun, weil es, was ein Wörterbuch ist bereits der Fall ist. Wenn Sie dict[key] holen Sie wissen,, ob das Wörterbuch den Schlüssel enthält, weil das Optional, das Sie zurück erhalten, nicht nil ist (und es den Wert enthält).

Also, wenn Sie nur die Frage beantworten wollen, ob das Wörterbuch den Schlüssel enthält, fragen:

let keyExists = dict[key] != nil 

Wenn Sie den Wert wollen, und Sie wissen das Wörterbuch den Schlüssel enthält, sagen:

let val = dict[key]! 

wenn aber, wie in der Regel der Fall ist, Sie wissen nicht, den Schlüssel enthält - wollen Sie es holen und es verwenden, aber nur, wenn es vorhanden ist - dann so etwas wieverwenden: einen Wert für einen Schlüssel zu bekommen, oder einfach nur den ersten Wert

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

Ich folge nicht. Ich habe nur einen Wert (zweimal) erhalten. Was willst du noch? – matt

+0

Es gibt keinen "ersten Wert". ein Wörterbuch ist ungeordnet. Wenn Sie nur die Werte ohne die Schlüssel möchten, sagen Sie 'dict.values'. – matt

+0

Hier ist der Teil meines Tutorials, in dem ich über Wörterbücher erkläre: http://www.apeth.com/swiftBook/ch04.html#_dictionary – matt

5

Sieht aus wie Sie bekommen, was Sie von @ Matt brauchen, aber wenn Sie eine schnelle Art und Weise wollen, wenn die Schlüssel nicht existiert:

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”} 

Hinweis, keine Garantie, was Sie tatsächlich als den ersten Wert erhalten, es passiert nur in diesem Fall, um "rot" zurückzugeben.

+0

gute Verwendung des Operators '??' nahm meine Convenience-Lösung von mir, aber als Erweiterung konnte dieser Standardwert Daten Unsicherheiten oder unerwartetes Verhalten darstellen. Das klingt nach etwas, was eine konkrete Unterklasse von 'Dictionary' verwenden sollte. Wie oft benötigen Sie den ersten Wert im Falle einer "Null" -Rückkehr ohne situationsspezifische Funktionalität? –

14

Warum nicht einfach nach dict.keys.contains(key) suchen? Die Überprüfung auf dict[key] != nil funktioniert nicht in Fällen, in denen der Wert Null ist. Wie mit einem Wörterbuch [String: String?] zum Beispiel.

+1

Oder anstatt einfach zu schreiben 'if let val = dict [key]' kannst du 'if val = dict [key] als verwenden? String in diesem Fall. –

+0

.keys.contains hilft nicht bei der Unterscheidung, ob der Schlüssel vorhanden ist oder ob der Wert gleich null ist. Vielleicht in früheren schnellen Versionen? Funktioniert nicht für mich in swift 4. –

0

Meine Lösung für eine Cache-Implementierung, die optional NSAttributedString speichert:

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

Hier ist, was auf Swift funktioniert für mich 3

let _ = (dict[key].map { $0 as? String } ?? "") 
0
if dictionayTemp["quantity"] != nil 
    { 

    //write your code 
    } 
3

Die Antwort akzeptiert let keyExists = dict[key] != nil nicht, wenn die Arbeit Das Wörterbuch enthält den Schlüssel, hat aber einen Wert von Null.

Wenn Sie sicher sein wollen, dass das Wörterbuch den Schlüssel überhaupt nicht enthält, verwenden Sie dies (getestet in Swift 4).

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