Maitriser les tableaux en JavaScript (FP)

Lorsque l’on débute dans un langage de programmation, il est souvent facile de reproduire ce que l’on a l’habitude de faire dans les langages que l’on connait déjà.

Dans l’absolu, c’est une très bonne façon de faire :

  • Les structures conditionnelles, itératives, etc, restent les mêmes malgré quelques différences sémantiques.
  • Le développeur gagne du temps dans son apprentissage. Réutiliser / capitaliser sur ses connaissances est une des clés de la réussite.

Malheureusement, cette façon de faire possède aussi un inconvénient. Comme on ne s’attarde pas sur certaines notions, on se prive de subtilité du langage qui pourraient pourtant nous aider.

J’en veux pour preuve cet exemple :

let tableau = [3, 2, 5, 1, 6, 6]

function add15(tab) {
  for (let i = 0; i < tab.length; i++) {
    tab[i] += 15
  }
  
  return tab
}

let tableau15 = add15(tableau)

Ce code fonctionne. Il est tout à fait correcte. On ferait comme ça dans plusieurs langages.

let tableau15 = [3, 2, 5, 1, 6, 6].map(el => el + 15)

Mais voici le code que je peux écrire lorsque j’ai connaissance des subtilités du JavaScript. (Si la syntaxe de mes callbacks vous choque, je vous invite à aller lire mon article sur les fonctions fléchées.)

Le but n’étant pas de réécrire la documentation officielle, je vais m’arrêter à trois méthodes de l’objet Array peu ou pas connus des développeurs. Peut-être les trois méthodes qu’il vous manque pour maitriser les tableaux en JavaScript.

Modifier itérativement un tableau

Pour modifier itérativement un tableau en JavaScript on utilise la méthode Array.map qui prend en paramètre un callback de cette forme :

(elementCourant) => {
  return valeurDeRemplacement
}

Nous l’avons utilisé ci-dessus pour additionner toutes les valeurs du tableau au nombre 15.

La méthode Array.map est une pure function, elle ne modifie pas le tableau sur lequel elle travaille, mais retourne une copie modifiée.

Filtrer les valeurs d’un tableau

Le filtrage d’un tableau suit la même logique. La méthode Array.filter prend aussi un callback en paramètre. Ce callback nous donne aussi accès à l’élément courant.

Ce qu’attend Array.filter de ce callback, c’est de décider si oui ou non il faut garder l’élément courant dans le tableau.

(elementCourant) => {
  return condition
}

Le callback retourne donc true s’il faut garder l’élément et false s’il ne faut pas garder cet élément.

Si l’on veut, par exemple, ne garder d’un tableau uniquement les valeurs inférieures ou égales à 3 :

const tab = [3, 2, 5, 1, 6, 6].filter(el => el <= 3)

Là aussi, la méthode ne modifie pas le tableau, mais en retourne un nouveau avec uniquement les valeurs qui répondent au test.

Trier les valeurs d’un tableau

Pour le tri, c’est la méthode Array.sort qui entre en jeu. Elle fonctionne de la même façon que les autres, mais modifie le tableau sur lequel elle travaille en plus d’en retourner une copie. Ce n’est pas une pure function.

La méthode prend aussi un callback qui lui indique comment agir sur le tableau.

Pour trier deux valeurs, on les compare et on décide quel élément doit être devant l’autre.

(elementUn, elementDeux) => {
  return sens
}

Le sens peut être égale à 0, supérieur à 0 ou inférieur à 0.

Lorsqu’il est supérieur à 0 elementDeux sera situé avant elementUn. Par exemple ['coucou', 'toi'] deviendra ['toi', 'coucou'].

Lorsqu’il est inférieur à 0, c’est l’inverse : elementDeux sera situé après elementUn.

Lorsqu’il est égal à 0, il n’y a rien qui bouge. On considère que l’on est sur une égalité des deux éléments.

Pour trier un tableau qui ne contient que des valeurs numériques par ordre croissant :

const tab = [3, 2, 5, 1, 6, 6].sort((a, b) => a - b)

Si a est plus grand que b, la valeur de retour sera positive donc b passera devant a. Inversement lorsque la valeur de retour est négative.

Functional Programming

On ne se rend pas bien compte comme ça, mais ces trois méthodes de l’objet Array vous permettent de faire énormément de choses !

Un exemple ? Admettons que l’on veuille savoir si dans un tableau il existe une valeur qui une fois multipliée par elle-même est supérieure à 88.

Je ne vais pas vous expliquer ce qu’est le Functional Programing ici. Le but est de vous montrer par l’exemple ce qu’il est possible de faire avec les méthodes de tableaux vu plus haut et à quel point elles peuvent changer votre manière de développer.

const arr = [3, 2, 5, 1, 6, 6]

function test(tab) {
  for (let item of tab) {
    let square = item * item

    if (square > 88) {
      return true
    }
  }
  
  return false
}

const exist = test(arr)

C’est la traduction de la demande en algorithme. Pas compliqué, il suffit de lire.

const exist = [3, 2, 5, 1, 6, 6]
  .map(x => x * x)
  .filter(x => x > 88)
  .length > 0

La version Functional Programming n’est pas mal non plus.


Pour aller plus loin :