Tableau à partir des clés du dictionnaire dans swift

256

Essayer de remplir un tableau avec des chaînes à partir des clés d'un dictionnaire en swift.

var componentArray: [String]

let dict = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("Components", ofType: "plist")!)
componentArray = dict.allKeys

Cela renvoie une erreur de: «AnyObject» non identique à la chaîne

A également essayé

componentArray = dict.allKeys as String 

mais obtenez: 'String' n'est pas convertible en [String]

Kyle Goslan
la source

Réponses:

534

Swift 3 et Swift 4

componentArray = Array(dict.keys) // for Dictionary

componentArray = dict.allKeys // for NSDictionary
Andrius Steponavičius
la source
Fait intéressant, dans une boucle for - pour le nom dans dict.allKeys - 'name' devient une chaîne et peut être imprimé et autrement traité.
green_knight
dict n'a pas de méthode de touches. C'est une instance de NSDictionary, pas un dictionnaire.
Womble
2
dict.map {$ 0.key}
Nilanshu Jaiswal
55

Avec Swift 3, Dictionarya une keyspropriété. keysa la déclaration suivante:

var keys: LazyMapCollection<Dictionary<Key, Value>, Key> { get }

Une collection contenant uniquement les clés du dictionnaire.

Notez que LazyMapCollectioncela peut facilement être mis en correspondance avec un Arrayavec Arrayde » init(_:)l'initialiseur.


De NSDictionaryau[String]

L' AppDelegateextrait de classe iOS suivant montre comment obtenir un tableau de chaînes ( [String]) à l'aide keysd'une propriété à partir d'un NSDictionary:

entrez la description de l'image ici

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let string = Bundle.main.path(forResource: "Components", ofType: "plist")!
    if let dict = NSDictionary(contentsOfFile: string) as? [String : Int] {
        let lazyMapCollection = dict.keys
        
        let componentArray = Array(lazyMapCollection)
        print(componentArray)
        // prints: ["Car", "Boat"]
    }
    
    return true
}

Du [String: Int]au[String]

De manière plus générale, le code Playground suivant montre comment obtenir un tableau de chaînes ( [String]) en utilisant la keyspropriété d'un dictionnaire avec des clés de chaîne et des valeurs entières ( [String: Int]):

let dictionary = ["Gabrielle": 49, "Bree": 32, "Susan": 12, "Lynette": 7]
let lazyMapCollection = dictionary.keys

let stringArray = Array(lazyMapCollection)
print(stringArray)
// prints: ["Bree", "Susan", "Lynette", "Gabrielle"]

Du [Int: String]au[String]

Le code Playground suivant montre comment obtenir un tableau de chaînes ( [String]) en utilisant la keyspropriété d'un dictionnaire avec des clés entières et des valeurs de chaîne ( [Int: String]):

let dictionary = [49: "Gabrielle", 32: "Bree", 12: "Susan", 7: "Lynette"]
let lazyMapCollection = dictionary.keys
    
let stringArray = Array(lazyMapCollection.map { String($0) })
// let stringArray = Array(lazyMapCollection).map { String($0) } // also works
print(stringArray)
// prints: ["32", "12", "7", "49"]
Imanou Petit
la source
merci pour le détail. Dans Swift 4.x, le type est Dictionary<String, String>.Keys- avez-vous une idée quand nous voudrions utiliser ce type et comment?
bshirley
46

Tableau à partir des clés de dictionnaire dans Swift

componentArray = [String] (dict.keys)
Santo
la source
Je ne sais pas pourquoi les gens ne préfèrent pas la syntaxe raccourcie alors qu'elle est beaucoup plus claire à comprendre.
Natasha
9

dict.allKeysn'est pas une chaîne. C'est un [String], exactement comme le message d'erreur vous l'indique (en supposant, bien sûr, que les clés sont toutes des chaînes; c'est exactement ce que vous affirmez lorsque vous dites cela).

Donc, commencez par taper componentArrayas [AnyObject], car c'est ainsi qu'il est tapé dans l'API Cocoa, ou bien, si vous transtypez dict.allKeys, transtypez-le [String], car c'est ainsi que vous avez tapé componentArray.

mat
la source
1
Cela ne semble plus vrai. Dans Swift 4.2 dict.keys (qui remplace .allKeys) n'est pas une [String], c'est un [Dictionary <String, Any> .Keys] et doit être casté avant d'être affecté à une variable de type [String] @santo semble avoir l'exemple de travail le plus simple de la façon de le faire.
timeSmith
5
extension Array {
    public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
        var dict = [Key:Element]()
        for element in self {
            dict[selectKey(element)] = element
        }
        return dict
    }
}
Jitesh Desai
la source
3

NSDictionary est une classe (passe par référence) Dictionary est une structure (passe par valeur ) ====== Tableau de NSDictionary ======NSDictionary est un type de classe Le dictionnaire est la structure de la clé et de la valeur

NSDictionary a allKeys et allValues obtiennent des propriétés de type [Any] .NSDictionary possède des propriétés [Any] pour allkeys et allvalues

  let objesctNSDictionary = 
    NSDictionary.init(dictionary: ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"])
            let objectArrayOfAllKeys:Array = objesctNSDictionary.allKeys
            let objectArrayOfAllValues:Array = objesctNSDictionary.allValues
            print(objectArrayOfAllKeys)
            print(objectArrayOfAllValues)

====== Tableau du dictionnaire ======

Référence Apple pour les propriétés des clés et valeurs du dictionnaire . entrez la description de l'image ici

entrez la description de l'image ici

let objectDictionary:Dictionary = 
            ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
    let objectArrayOfAllKeys:Array = Array(objectDictionary.keys)          
    let objectArrayOfAllValues:Array = Array(objectDictionary.values)
    print(objectArrayOfAllKeys)
    print(objectArrayOfAllValues)
Darshan Panchal
la source
3

À partir de la documentation officielle d' Array Apple :

init(_:) - Crée un tableau contenant les éléments d'une séquence.

Déclaration

Array.init<S>(_ s: S) where Element == S.Element, S : Sequence

Paramètres

s - La séquence d'éléments à transformer en tableau.

Discussion

Vous pouvez utiliser cet initialiseur pour créer un tableau à partir de tout autre type conforme au protocole Sequence ... Vous pouvez également utiliser cet initialiseur pour reconvertir une séquence complexe ou un type de collection en tableau. Par exemple, la propriété keys d'un dictionnaire n'est pas un tableau avec son propre stockage, c'est une collection qui mappe ses éléments à partir du dictionnaire uniquement lorsqu'ils sont accédés, économisant ainsi le temps et l'espace nécessaires pour allouer un tableau. Si vous devez cependant transmettre ces clés à une méthode qui prend un tableau, utilisez cet initialiseur pour convertir cette liste à partir de son type LazyMapCollection<Dictionary<String, Int>, Int> to a simple [String].

func cacheImagesWithNames(names: [String]) {
    // custom image loading and caching
 }

let namedHues: [String: Int] = ["Vermillion": 18, "Magenta": 302,
        "Gold": 50, "Cerise": 320]
let colorNames = Array(namedHues.keys)
cacheImagesWithNames(colorNames)

print(colorNames)
// Prints "["Gold", "Cerise", "Magenta", "Vermillion"]"
Chris Graf
la source
2

Vous pouvez utiliser dictionary.map comme ceci:

let myKeys: [String] = myDictionary.map{String($0.key) }

L'explication: la carte parcourt le myDictionary et accepte chaque paire de clés et de valeurs comme $ 0. De là, vous pouvez obtenir $ 0.key ou $ 0.value. À l'intérieur de la fermeture arrière {}, vous pouvez transformer chaque élément et renvoyer cet élément. Puisque vous voulez $ 0 et que vous le voulez sous forme de chaîne, vous convertissez en utilisant String ($ 0.key). Vous collectez les éléments transformés dans un tableau de chaînes.

Flûte Meo
la source
1

Cette réponse sera pour le dictionnaire rapide avec des clés de chaîne. Comme celui-ci ci-dessous .

let dict: [String: Int] = ["hey": 1, "yo": 2, "sup": 3, "hello": 4, "whassup": 5]

Voici l'extension que j'utiliserai.

extension Dictionary {
  func allKeys() -> [String] {
    guard self.keys.first is String else {
      debugPrint("This function will not return other hashable types. (Only strings)")
      return []
    }
    return self.flatMap { (anEntry) -> String? in
                          guard let temp = anEntry.key as? String else { return nil }
                          return temp }
  }
}

Et j'obtiendrai toutes les clés plus tard en utilisant ceci.

let componentsArray = dict.allKeys()
jnblanchard
la source
1

Swift 5

var dict = ["key1":"Value1", "key2":"Value2"]

let k = dict.keys

var a: [String]()
a.append(contentsOf: k)

Cela fonctionne pour moi.

Siddharth Kavthekar
la source
-2
// Old version (for history)
let keys = dictionary.keys.map { $0 }
let keys = dictionary?.keys.map { $0 } ?? [T]()

// New more explained version for our ducks
extension Dictionary {

    var allKeys: [Dictionary.Key] {
        return self.keys.map { $0 }
    }
}
Igor Bachek
la source
2
Héy! Bien que cet extrait de code puisse être la solution, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
Wing