# 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.