Les dictionnaires sont des structures de données qui permettent de stocker et d'organiser des informations de manière associative. Chaque élément d'un dictionnaire est composé d'une clé et d'une valeur correspondante.

Ils permettent de stocker des données de manière efficace et de les récupérer rapidement en utilisant des clés uniques.

Dictionnaire

Pour déclarer un dictionnaire en Swift, on sépare les clés des valeurs par le symbole deux-points (:). Les différentes clés et leurs valeurs associées sont séparées par des virgules (,) et le tout est encadré par des crochets ([ ]).


var monDictionnaire = [
    "cle1": "valeur1",
    "cle2": "valeur2"
]

Dans un exemple plus concret, cela se traduirait par :


let fruits = ["pomme": 3, "banane": 5, "orange": 2]

Dans l'exemple ci-dessus, grâce à l'inférence de type, Swift en déduit qu'il s'agit d'un dictionnaire. La première clé se nomme pomme et a pour valeur 3, la deuxième clé se nomme banane et a pour valeur 5 et, enfin, la troisième clé se nomme orange et a pour valeur 2.

Les clés doivent toutes être du même type et les valeurs doivent également toutes être du même type.

Ce dictionnaire possède des clés de type String et des valeurs de type Int. Il est donc de type [String: Int].

Les clés d'un dictionnaire doivent toutes être du même type et les valeurs doivent également être du même type. Cependant, le type des clés et celui des valeurs peuvent être différents. Les clés doivent par ailleurs respecter le protocole Hashable. Les types courants comme String, Int ou Bool respectent déjà ce protocole.

Dictionnaire vide

Si on a besoin de déclarer un dictionnaire vide, on peut le faire soit explicitement à l'aide d'une annotation de type, soit en utilisant une syntaxe permettant à Swift de déterminer le type du dictionnaire :


// Déclaration d'un dictionnaire vide

// Avec une annotation de type
var dictionnaireVide: [String: Int] = [:]

// Avec l'initialiseur du type Dictionary
var autreDictionnaireVide = [String: Int]()

Dans les deux lignes de code ci-dessus, nous déclarons d'abord le dictionnaire dictionnaireVide avec une annotation de type, puis le dictionnaire autreDictionnaireVide avec l'initialiseur du type [String: Int]. Ces deux dictionnaires sont vides et sont tous les deux de type [String: Int].

La déclaration de leur type permet de sécuriser les futures entrées. Ces dictionnaires ne pourront recevoir que des clés de type String et des valeurs de type Int . Toute tentative d'ajouter une clé ou une valeur d'un autre type provoquera une erreur de compilation.

Comme les tableaux, les dictionnaires peuvent être déclarés sous la forme d'une constante ou d'une variable. Utilisez let si leur contenu ne doit pas changer et var si vous souhaitez ajouter, modifier ou supprimer des éléments.

Itérer un dictionnaire

Beaucoup de notions vous paraîtront plus simples aujourd'hui. Le fonctionnement des dictionnaires est très similaire à celui des tableaux que nous avons étudiés dans le chapitre précédent. À commencer par l'itération : pour parcourir un dictionnaire, on utilise la boucle for.

Lors de l'itération, chaque élément du dictionnaire est renvoyé sous la forme d'un tuple. Vous pouvez décomposer les membres de ce tuple en constantes utilisables uniquement à l'intérieur du corps de la boucle.


let nombreDePattes = ["araignée": 8, "fourmi": 6, "chat": 4]

for (nom, nombre) in nombreDePattes {
    print("\(nom) possède \(nombre) pattes")
}

// Exemple de résultat, dont l'ordre peut varier :
// chat possède 4 pattes
// fourmi possède 6 pattes
// araignée possède 8 pattes

Le contenu d'un dictionnaire ne possède pas d'ordre défini et, lors de son itération, rien ne garantit l'ordre dans lequel ses éléments seront récupérés. En particulier, l'ordre dans lequel vous insérez les éléments dans un dictionnaire ne détermine pas l'ordre dans lequel ils seront parcourus.

Il est également possible de ne parcourir que les clés ou que les valeurs d'un dictionnaire grâce aux propriétés keys et values :


let capitales = ["France": "Paris", "Belgique": "Bruxelles", "Suède": "Stockholm"]

for pays in capitales.keys {
    print("Quelle est la capitale de \(pays) ?")
}

// Exemple de résultat, dont l'ordre peut varier :
// Quelle est la capitale de la France ?
// Quelle est la capitale de la Belgique ?
// Quelle est la capitale de la Suède ?

for ville in capitales.values {
    print("\(ville) est la capitale de quel pays ?")
}

// Exemple de résultat, dont l'ordre peut varier :
// Paris est la capitale de quel pays ?
// Bruxelles est la capitale de quel pays ?
// Stockholm est la capitale de quel pays ?

Lors de la première boucle, on parcourt l'ensemble des clés du dictionnaire. La seconde boucle est consacrée aux valeurs de ce dictionnaire.

Manipuler un dictionnaire

Compter le nombre d'éléments clé-valeur dans un dictionnaire

La propriété count permet de connaître le nombre de paires clé-valeur présentes dans un dictionnaire. C'est un moyen simple de savoir combien d'éléments sont stockés dans votre dictionnaire à un moment donné.

Voici comment cela fonctionne :


let fruits = ["pomme": 3, "banane": 5, "orange": 2]

let nombreElements = fruits.count

print(nombreElements)
// Cela affichera : 3

Comme pour les tableaux, on accède à la propriété count d'un dictionnaire en indiquant le nom du dictionnaire, suivi d'un point et du mot count.

Vérifier si un dictionnaire est vide

Pour vérifier si un dictionnaire est vide, il est préférable d'utiliser la propriété isEmpty plutôt que de comparer la propriété count à 0 :


let fruits = ["pomme": 3, "banane": 5, "orange": 2]

if fruits.isEmpty {
    print("Le dictionnaire est vide")
} else {
    print("Le dictionnaire contient au moins un élément")
}

// Cela affichera :
// Le dictionnaire contient au moins un élément

Ajouter une valeur à un dictionnaire

Pour ajouter un nouvel élément, on utilise une nouvelle fois la syntaxe d'indice. Vous remarquerez que cette syntaxe est pratique et rend le code particulièrement lisible. Il suffit d'indiquer une nouvelle clé et de lui affecter une valeur :


var fruits = ["pomme": 3, "banane": 5, "orange": 2]

fruits["kiwi"] = 4
// Ajoute la paire clé-valeur "kiwi": 4 au dictionnaire

Attention, le type de la nouvelle clé doit être identique au type des autres clés du dictionnaire. Il en va de même pour les valeurs : la nouvelle valeur doit être du même type que les autres valeurs du dictionnaire.

C'est dans l'utilisation des clés pour obtenir ou manipuler les valeurs correspondantes que les différences entre les tableaux et les dictionnaires sont les plus visibles. Grâce à sa clé, une valeur peut être retrouvée de manière simple, rapide et lisible. Avec un dictionnaire, vous n'avez pas à connaître la position d'une valeur : il vous suffit de connaître sa clé.

Modifier une valeur d'un dictionnaire

Pour modifier la valeur associée à une clé, il vous suffit d'affecter une nouvelle valeur à cette clé. On utilise toujours la syntaxe d'indice en indiquant la clé dont on souhaite modifier la valeur :


var fruits = ["pomme": 3, "banane": 5, "orange": 2]

fruits["banane"] = 8
// La valeur associée à la clé "banane" est maintenant égale à 8

Accéder aux valeurs d'un dictionnaire

En Swift, on peut accéder à un élément d'un dictionnaire grâce à la syntaxe d'indice. On utilise une clé pour obtenir la valeur correspondante :


let fruits = ["pomme": 3, "banane": 5, "orange": 2]

let nombreDePommes = fruits["pomme"]
// nombreDePommes est de type Int? et contient ici la valeur optionnelle 3

Malheureusement, tout n'est pas toujours aussi simple qu'on le souhaiterait. On utilise bien la syntaxe d'indice pour récupérer la valeur associée à une clé particulière. Cependant, comme il est possible de demander une clé qui n'existe pas dans le dictionnaire, cette opération renvoie une valeur optionnelle. Ainsi, pour un dictionnaire de type [String: Int], une recherche effectuée à partir d'une clé renvoie une valeur de type Int?.

Les valeurs optionnelles sont un concept que nous découvrirons plus tard dans ce tutoriel. Pour faire simple, une valeur optionnelle peut contenir une valeur ou représenter son absence. Une valeur absente n'est pas équivalente à une chaîne de caractères vide ou au nombre zéro : elle est représentée en Swift par la valeur nil.

Dans l'exemple ci-dessous, si le dictionnaire contient une valeur correspondant à la clé demandée, cette valeur est extraite de l'optionnel et stockée dans une constante temporaire nommée fruit. Sinon, le dictionnaire renvoie nil et la branche else est exécutée :


let fruits = ["pomme": 3, "banane": 5, "orange": 2]

if let fruit = fruits["pomme"] {
    print("Il en reste \(fruit)")
} else {
    print("Ce fruit n'est pas dans notre dictionnaire")
}

// Cela affichera :
// Il en reste 3

Il s'agit d'une condition if un peu particulière, appelée liaison optionnelle. Nous reviendrons en détail sur celle-ci dans le chapitre consacré au type optionnel. Pour le moment, l'important est de comprendre que l'on utilise une clé entre crochets pour accéder à la valeur correspondante.

Supprimer un élément du dictionnaire

La syntaxe d'indice étant omniprésente dans la manipulation d'un dictionnaire, nous l'utiliserons une nouvelle fois pour supprimer une paire clé-valeur. Il suffit d'affecter la valeur nil à la clé concernée :


var fruits = ["pomme": 3, "banane": 5, "orange": 2]

fruits["banane"] = nil

print(fruits)
// Exemple de résultat, dont l'ordre peut varier :
// ["pomme": 3, "orange": 2]
En Swift, la valeur nil représente l'absence de valeur. Elle peut notamment être affectée à une variable optionnelle. Dans le cas d'un dictionnaire, affecter nil à une clé permet de supprimer la paire clé-valeur correspondante.

On peut également utiliser la méthode removeValue(forKey:). On applique cette méthode au dictionnaire en indiquant, pour le paramètre nommé forKey:, la clé de l'élément à supprimer :


var fruits = ["pomme": 3, "banane": 5, "orange": 2]

fruits.removeValue(forKey: "banane")

print(fruits)
// Exemple de résultat, dont l'ordre peut varier :
// ["pomme": 3, "orange": 2]

Après les tableaux, vous êtes désormais capable d'utiliser des dictionnaires. Prenez toujours quelques instants pour regarder derrière vous et mesurer le parcours que vous avez déjà effectué. Soyez-en fier. Vos capacités de futur développeur grandissent de jour en jour.

Dès le prochain chapitre, nous allons découvrir le dernier type de collection : les ensembles.

  • Chaque élément d'un dictionnaire est composé d'une clé et d'une valeur correspondante.
  • Chaque clé est unique.
  • Les clés doivent toutes être du même type et les valeurs doivent également toutes être du même type.
  • Les clés d'un dictionnaire doivent respecter le protocole Hashable.
  • Lors de l'itération, rien ne garantit l'ordre dans lequel les éléments du dictionnaire seront récupérés.

Je vous conseille de faire chaque exercice de fin de chapitre. Cela consolidera votre apprentissage de manière efficace en vous permettant de passer de la théorie à la pratique. Faites vos propres expériences, n'ayez peur de rien : vous progresserez plus vite ainsi.

Pour cet exercice, nous partirons d'une base commune : le dictionnaire ci-dessous, nommé personnes. Vous devrez ensuite sélectionner toutes les personnes âgées de moins de 25 ans et les enregistrer dans un nouveau dictionnaire. Cela ne devrait pas vous poser de problème.


let personnes = ["Jean": 65, "Ludivine": 12, "François": 71, "Michelle": 44, "Laura": 24]

let personnes = ["Jean": 65, "Ludivine": 12, "François": 71, "Michelle": 44, "Laura": 24]

// On déclare un dictionnaire vide de type [String: Int]
var jeunes: [String: Int] = [:]

// On sélectionne les personnes âgées de moins de 25 ans
// pendant l'itération du dictionnaire.

for (nom, age) in personnes {
    if age < 25 {
        // Si l'âge est inférieur à 25 ans, on l'enregistre
        // dans le nouveau dictionnaire.
        jeunes[nom] = age
    }
}

print(jeunes)

// Exemple de résultat, dont l'ordre peut varier :
// ["Laura": 24, "Ludivine": 12]