web-dev-qa-db-fra.com

Différence entre flatMap et compactMap dans Swift

Il semble que dans Swift 4.1flatMap soit obsolète. Cependant il y a une nouvelle méthode dans Swift 4.1compactMap qui fait la même chose? Avec flatMap, vous pouvez transformer chaque objet dans une collection, puis supprimer tous les éléments nuls.
comme flatMap

let array = ["1", "2", nil] 
array.flatMap { $0 } // will return "1", "2"

comme compactMap

let array = ["1", "2", nil] 
array.compactMap { $0 } // will return "1", "2"

compactMap fait la même chose.

Quelles sont les différences entre ces 2 méthodes? Pourquoi Apple a-t-il décidé de renommer la méthode?

18
BilalReffas

Il existe trois variantes différentes de flatMap. La variante de Sequence.flatMap(_:) qui accepte une fermeture renvoyant une valeur facultative est obsolète. Les autres variantes de flatMap(_:) sur Séquence et Facultatif restent telles quelles. La raison expliquée dans le document de proposition est due à une mauvaise utilisation.

La fonctionnalité de variante flatMap obsolète est exactement la même sous une nouvelle méthode compactMap.

Voir les détails ici .

18
Bilal

La bibliothèque standard Swift définit 3 surcharges pour la fonction flatMap:

Sequence.flatMap<S>(_: (Element) -> S) -> [S.Element]  
Optional.flatMap<U>(_: (Wrapped) -> U?) -> U?  
Sequence.flatMap<U>(_: (Element) -> U?) -> [U]  

La dernière fonction de surcharge peut être utilisée de deux manières:
Envisagez la structure et le tableau suivants:

struct Person {
  var age: Int
  var name: String
}  

let people = [Person(age: 21, name: "Osame"), Person(age: 17, name: "Masoud"), Person(age: 20, name: "Mehdi")]  

Première façon: emballage et déballage supplémentaires:
Si vous aviez besoin d'obtenir un tableau d'âges de personnes inclus dans le tableau people, vous pourriez utiliser deux fonctions:

let flatMappedAges = people.flatMap({$0.age})  // prints: [21, 17, 20]
let mappedAges = people.map({$0.age})  // prints: [21, 17, 20]  

Dans ce cas, la fonction map fera le travail et il n'est pas nécessaire d'utiliser flatMap, car les deux produisent le même résultat. De plus, il y a un processus inutile d'emballage et de déballage dans ce cas d'utilisation de flatMap. (Le paramètre de fermeture enveloppe sa valeur retournée avec un Facultatif et l'implémentation de flatMap déballe la valeur Facultative avant de la retourner)

Deuxième méthode - Conformité des chaînes au protocole de collecte:
Pensez que vous devez obtenir une liste des noms des personnes à partir du tableau people. Vous pouvez utiliser la ligne suivante:

let names = people.flatMap({$0.name})  

Si vous utilisiez une version Swift antérieure à 4.0, vous obtiendrez une liste transformée de

["Osame", "Masoud", "Mehdi"]  

mais dans les versions plus récentes, String est conforme au protocole Collection, donc, votre utilisation de flatMap() correspondrait à la première fonction de surcharge au lieu de la troisième et vous donnerait un résultat aplati de vos valeurs transformées:

["O", "s", "a", "m", "e", "M", "a", "s", "o", "u", "d", "M", "e", "h", "d", "i"]

Conclusion: ils ont déconseillé la troisième surcharge de flatMap ()
En raison de ces abus, Swift a décidé de déconseiller la troisième surcharge à la fonction flatMap. Et leur solution au cas où vous devez faire face à Optionals jusqu'ici consistait à introduire une nouvelle fonction appelée compactMap() qui vous donnera le résultat attendu.

20
Mehdi