Écrit par Reinder de Vries le 12 juillet 2020 dans Développement d’applications, Swift
Swift a un tas de fonctions utiles pour transformer des collections et des séquences. Dans ce tutoriel, nous allons discuter de map(_:)
, flatMap(_:)
et compactMap(_:)
.
Voici ce sur quoi nous allons nous concentrer:
- Comment
map(_:)
transforme une collection ou une séquence en lui appliquant une fermeture - Comment
flatMap(_:)
peut aplatir un tableau d’entrée, après avoir appelémap(_:)
- Comment
compactMap(_:)
supprimenil
du tableau d’entrée
Dans un tutoriel précédent, nous avons discuté de la façon dont vous pouvez utiliser
- Comment
map(_:)
- Comment
compactMap(_:)
supprimenil
du tableau d’entrée
filter(_:) et reduce(_:)
. Ces fonctions d’ordre supérieur sont très utiles pour transformer les collections, de manière concise et perspicace.
Prêt? Allons-y.
- Utilisation de la Fonction Map dans Swift
- Utilisation de la Fonction FlatMap
- Utilisation de la Fonction CompactMap
- Pourquoi Utiliser FlatMap et CompactMap ?
- Lectures complémentaires
Vous ne connaissez pas encore les fermetures ou les fonctions d’ordre supérieur? Assurez-vous de les lire en premier:
- Le Guide ultime des fermetures dans Swift
- Cartographiez, Réduisez et filtrez dans Swift
En utilisant la fonction Map dans Swift
Comme rappel rapide sur les fonctions d’ordre supérieur dans Swift, notre point de départ est la fonction map(_:)
. Cette fonction applique une transformation à chacun des éléments d’une séquence, comme un tableau ou un dictionnaire.
Voici un exemple:
let result=numbers.carte({ $0 * $0 })
imprimer (résultat)
Décomposons cela:
Tout d’abord, nous créons un tableau numbers
avec quelques valeurs entières. Ensuite, la fonction map(_:)
est appelée sur numbers
et son résultat est affecté à result
.
La fonction map(_:)
a un paramètre, une fermeture, qui renvoie le résultat de . Le
correspond au premier paramètre de la fermeture, c’est-à-dire le nombre de
numbers
qui est transformé.
Nous calculons le carré de chaque nombre dans numbers
. En substance, l’opération est appelée sur chaque nombre de
numbers
, et le tableau résultant est affecté à result
. Vous transformez – ou « mappez » – un tableau en un autre.
Transformer un tableau avec map(_:)
est similaire à l’utilisation d’une boucle for, mais beaucoup plus concis. Comme ça:
let numbers = var result = ()for number in numbers { result += }print(result)
Voici une autre façon de le regarder. Avec map(_:)
, le tableau de nombres d’entrée est transformé en un autre tableau de nombres. Comme ça:
2 => 2 * 2 => 43 => 3 * 3 => 94 => 4 * 4 => 165 => 5 * 5 => 25
Des fonctions comme map(_:)
sont appelées fonctions d’ordre supérieur, car elles prennent une fonction en entrée par opposition aux valeurs ordinaires. Les fonctions d’ordre supérieur peuvent également produire des fonctions, ce qui est utile pour un paradigme de programmation appelé programmation fonctionnelle.
Techniquement, vous pouvez appeler des fonctions d’ordre supérieur comme map(_:)
sur n’importe quelle séquence. Cela inclut les collections telles que les tableaux, les dictionnaires et les ensembles, les plages telles que 1...100
et les soi-disant itérateurs. Tout ce qui ressemble à une « liste » de valeurs, en gros.
Nous expliquerons pourquoi les fonctions d’ordre supérieur sont utiles à la fin de ce tutoriel. Passons d’abord à en savoir plus sur flatMap(_:)
et compactMap(_:)
.

Soyez embauché en tant que développeur iOS
Apprenez à créer des applications iOS 14 avec Swift 5
Inscrivez-vous à mon cours de développement iOS et apprenez à démarrer votre carrière en tant que développeur iOS professionnel.
En utilisant la fonction FlatMap
, la fonction flatMap(_:)
est similaire à map(_:)
, sauf qu’elle « aplatit » le tableau résultant. Voici un exemple:
let result=numbers.flatMap({00})
imprimer (résultat)
Le code ci-dessus commence par un tableau imbriqué d’entiers. Le tableau numbers
se compose d’un tableau de 3 tableaux, chacun contenant 3 nombres.
La fermeture { }
renvoie simplement le premier argument de la fermeture, c’est-à-dire les tableaux imbriqués individuels. Aucune transformation ou opération n’a lieu. Lorsque vous appelez flatMap(_:)
sur le tableau numbers
, au lieu de map(_:)
, vous vous retrouvez avec un tableau aplati de nombres individuels. Contrairement au tableau d’entrée numbers
, le tableau de résultat ne contient pas de tableaux imbriqués !
Regardons un autre exemple. Imaginez que vous travaillez avec 4 groupes de girafes et que vous souhaitez créer un seul groupe de girafes plus hautes qu’une certaine hauteur. Voici comment vous faites cela:
let plus haut = girafes.Carte plate ({00.filtre({ $0 > 10 }) })
imprimer (le plus haut)
Voir comment giraffes
contient un tableau de tableaux? Dans le code ci-dessus, la fonction filter(_:)
est appelée sur chaque tableau imbriqué à l’intérieur de giraffes
. Nous ne voulons que des entiers (girafes!) qui sont supérieures à 10
. Les tableaux résultants sont aplatis en un tableau « plat » et affectés à tallest
.
Considérez ce qui se passerait si nous avions utilisé map(_:)
au lieu de flatMap(_:)
. Le tableau résultant ne serait pas aplati. Au lieu de cela, ce serait ceci:
, , ]
Il est important de noter que la fonction flatMap(_:)
appelle d’abord map(_:)
sur les éléments du tableau, puis l’aplatit. C’est pourquoi quelque chose comme ce qui suit ne fonctionne pas:
let numbers = , , ]let result = numbers.flatMap({ * 2 })
Dans le code ci-dessus, fait référence aux tableaux à l’intérieur des nombres. Multiplier un tableau par deux est impossible, c’est pourquoi ce code ne fonctionne pas.
Il est intelligent de penser à la mise à plat comme voyant un tableau dans une dimension de moins. Vous commencez avec un tableau bidimensionnel et vous vous retrouvez avec un tableau unidimensionnel après flatMap(_:)
.
Qu’en est-il de l’utilisation de flatMap(_:)
avec des options? Regardons ça ensuite.
Le nom « carte compacte » est basé sur l’idée que la suppression des éléments nil
d’un tableau rend le tableau plus compact. De même, le nom « carte plate » vient de l’aplatissement du tableau. Et le « mappage » est un concept des mathématiques, où vous associez les valeurs d’un ensemble à un autre ensemble.
Utilisation de la fonction CompactMap
La fonction compactMap(_:)
supprime les valeurs nil
du tableau d’entrée. C’est super utile lorsque vous travaillez avec des options.
Avant Swift 4.1, la fonction flatMap(_:)
(ci-dessus) peut également être utilisée pour filtrer les valeurs nil
des tableaux aplatis. Depuis Swift 4.1+, vous utilisez maintenant le compactMap(_:)
explicite à cette fin.
Voici un exemple:
let result=numbers.compactMap({Int(00)})
print(résultat)
Voir ce qui se passe ? La partie la plus importante du code est Int()
. Cela prend une chaîne individuelle de numbers
avec et tente de convertir en un entier, avec l’initialiseur
Int()
.
Cet initialiseur Int()
est défaillant : il peut renvoyer nil
– une option – donc son type de retour est Int?
. En conséquence, le type de retour de la transformation de mappage est – un tableau d’entiers facultatifs.
La fonction compactMap(_:)
supprime automatiquement les éléments nil
du tableau renvoyé, après avoir appelé map(_:)
dessus. En tant que tel, son type de retour n’est pas facultatif.
Dans le code ci-dessus, le type de result
est . Si vous aviez utilisé
map(_:)
, le type de retour aurait été . Et vous auriez eu besoin d’une étape supplémentaire pour déballer les valeurs du tableau, pour travailler avec elles.
Pourquoi utiliser FlatMap et CompactMap ?
Avant de discuter des cas d’utilisation réels de flatmap et compactmap, résumons rapidement ces fonctions d’ordre supérieur et leurs objectifs.
- La fonction
map(_:)
applique une fermeture à une collection d’entrée et renvoie la collection transformée - La fonction
flatMap(_:)
fait la même chose, et elle aplatit également la collection résultante - La fonction
compactMap(_:)
fait la même chose quemap(_:)
, et elle supprime égalementnil
de la collection résultante
Travailler avec map(_:)
, flatMap(_:)
et compactMap(_:)
dans l’abstrait rend parfois difficile d’imaginer leurs cas d’utilisation pratiques. Discutons pourquoi vous voudriez les utiliser.
L’utilisation de fonctions telles que map(_:) pour appliquer des transformations à des séquences présente quelques avantages:
- C’est plus concis que d’utiliser une boucle
for
, car vous n’avez pas besoin de variables temporaires et d’un bloc multi-lignesfor in { }
. - Vous pouvez généralement écrire un appel à
map(_:)
sur une ligne, ce qui (généralement) rend votre code plus lisible. - Des fonctions comme
map(_:)
peuvent être enchaînées, vous pouvez donc appliquer plusieurs transformations à une séquence une par une.
En général, les fonctions d’ordre supérieur sont utiles car elles vous permettent d’appliquer une fonction à une séquence de valeurs. Au lieu de coder la transformation de manière procédurale, vous pouvez simplement appliquer la fonction et récupérer un résultat.
Le cas d’utilisation le plus pratique pour flatMap(_:)
consiste à travailler avec des valeurs d’entrée groupées ou imbriquées, mais la valeur de sortie souhaitée doit être unidimensionnelle.
Vous pouvez, dans une application musicale par exemple, avoir 3 tableaux: chansons, artistes et listes de lecture. Vous les combinez dans un tableau, appelez flatMap(_:)
dessus, sélectionnez les chansons, les artistes et les listes de lecture pour lesquels isFavorite
est true
, et vous vous retrouvez avec une liste plate d’éléments qui ont été favorisés.
Un cas d’utilisation pratique pour compactMap(_:)
fonctionne avec une transformation qui peut renvoyer nil
. Vous vous épargnez quelques étapes triviales en laissant compactMap(_:)
filtrer immédiatement les valeurs nil
. Un avantage supplémentaire est le type de retour non facultatif de compactMap(_:)
; la fonction filter(_:)
, en comparaison, aurait renvoyé une valeur facultative si vous aviez filtré nil
.
Vous pouvez combiner flatMap(_:)
et compactMap(_:)
, et même filter(_:)
ou reduce(_:_:)
. Imaginez que vous construisez une application de médias sociaux. Vous souhaitez construire une chronologie des publications pour un utilisateur. Vous utilisez 3 requêtes pour sélectionner les ID de publication de l’utilisateur, par exemple dans les publications des abonnés, les publicités et les sujets de tendance.
- Vous pouvez utiliser
map(_:)
pour étendre ces ID en objetsPost
réels - Vous pouvez utiliser
flatMap(_:)
pour aplatir les 3 groupes en une seule collection - Vous pouvez utiliser
compactMap(_:)
pour supprimer les publications qui n’ont pas pu être étendues
Neat!

Soyez embauché en tant que développeur iOS
Apprenez à créer des applications iOS 14 avec Swift 5
Inscrivez-vous à mon cours de développement iOS et apprenez à démarrer votre carrière en tant que développeur iOS professionnel.
Pour en savoir plus
Il vaut la peine de se renseigner sur map(_:)
, flatMap(_:)
et compactMap(_:)
, car ils rendent votre code plus concis et lisible. Vous pouvez ajouter une programmation plus fonctionnelle au code de votre application. Une fois que vous vous y êtes habitué, vous ne pouvez pas croire que vous pourriez faire votre travail sans eux.
En particulier, les différences entre map(_:)
, flatMap(_:)
et compactMap(_:)
méritent d’être soulignées. Le premier applique une transformation à une séquence, le second aplatit le tableau résultant et le troisième supprime les valeurs nil
avant de renvoyer son résultat. Fantastique!