# Rappels sur les API fonctionnelles des Array
Depuis ES5, il existe des méthodes du domaine de la programmation fonctionnelle sur les tableaux (Array
) :
Array.prototype.map
Array.prototype.filter
Array.prototype.reduce
et aussi (depuis ES6)
Array.prototype.find
Array.prototype.findIndex
Array.prototype.some
Array.prototype.every
Ce sont toutes des fonctions, et, mis à part reduce
(cf plus loin), elles prendront un seul paramètres : une fonction qui sera exécutée une fois par élément du tableau, avec, pour chaque élément du tableau, 3 arguments : l'élément en cours d'itération, l'index de l'élément, et le tableau d'origine. Toutes ces fonctions laisseront le tableau d’origine inchangé.
# map()
map()
sert à transformer chaque élément d'un tableau : il renverra toujours un nouveau tableau de la même taille que le tableau d'origine :
const celsiusFromFarenheit = x => (x - 32) / 1.8
const farenheit = [ 86, 68, 50, 32, 14]
const celsius = farenheit.map(celsiusFromFarenheit)
celsius // [ 30, 20, 10, 0, -10 ]
farenheit // [ 86, 68, 50, 32, 14]
N.B. : Le tableau d'origine n'est pas modifié (n'est pas muté).
# filter()
filter()
sert à garder une fraction du tableau : seulement les éléments dont la fonction passée en argument retourne true
pour l'élément :
const isPositive = x => x > 0
const positiveTmp = celsius.filter(isPositive)
positiveTmp // [ 30, 20, 10 ]
N.B. : Le tableau d'origine n'est pas muté non plus.
Remarque : Une fonction qui renvoie un booléen en fonction d'un input est appelée un prédicat.
# Chaînage de map()
et filter()
const positiveTmpInCelsius = farenheit
.map(celsiusFromFarenheit)
.filter(isPositive)
# reduce()
La méthode reduce()
permet de réduire une liste à une seule valeur (mais permet de faire des choses plus compliquée aussi). Elle prend 2 paramètres : une fonction de rappel, et une valeur d'origine.
La fonction de rappel fn
de reduce(fn)
recevra 4 arguments : un accumulateur (nous verrons ce qu'il signifie), puis les même 3 arguments que les autres méthodes : l'élément en cours d'itération, l'index de l'élément, et le tableau d'origine.
const getAverage = (accumulator, current, index, originalArray) => {
const total = accumulator + current
if (index === originalArray.length - 1) { // Dernier élément
return total / originalArray.length
}
return total
}
const average = celsius.reduce(getAverage, 0)
average // 10
On peut implémenter filter()
et map()
avec reduce()
en itérant une seule fois sur le tableau :
const positiveTmp2 = farenheit.reduce((acc, cur) => {
const inCelsius = celsiusFromFarenheit(cur)
if (inCelsius > 0) {
return [ // Création d'un nouveau tableau
...acc, // Ajout de tout ce qui est dans acc...
inCelsius // ...puis ajout de l'élément courant
]
}
return acc // le tableau acc inchangé
}, []) // Valeur initiale : tableau vide
N.B. : Pour des raisons de lisibilité, je pense que chaîner map()
et filter()
devrait être privilégié dans la plupart des cas.