Manipulation de tableaux avec JS
Christopher N. KATOYI
Posted on July 15, 2020
Pré-requis
- Des connaissances de base en Javascript
Niveau
- Intermédiaire
Les tableaux (aucun rapport avec Excel) sont des structures de données très utilisés en programmation. Ils permettent tout simplement la possibilité d'assigner à une seule et même variable, plusieurs données selon certaines règles qui diffèrent selon le langage que l'on utilise. Selon ce que l'on code, un site, une application, un CLI (acronyme pour Command Line Tool, un outil en ligne de commande, pour un usage dans un terminal), les données dans un tableau seront tôt ou tard nécessaires dans un traitement. Dans cet article, je vais parler des cas d'utilisation potentielle de ces données et comment gérer ces situations en Javascript.
Insérer des éléments dans un tableau
Un tableau est assez simple à déclarer.
1- Déclaration d'un tableau
La notation []
permet de déclarer un tableau vide et de l'assigner à la variable voulue. L'insertion des éléments dans un tableau se fait via la méthode .push(element)
où le paramètre element
représente ce que l'on insère dans un tableau. push
ajoute les éléments à la fin du tableau:
2- Insertion d'éléments dans un tableau
La méthode push
peut prendre plusieurs arguments qui iront dans le tableau dans l'ordre dans lequel ils sont entrés ! Il n'y a pas de restriction quant au type de données que l'on insère. Par exemple, j'y met ici des strings et un number.
Il existe un autre moyen plus concis d'écrire ce que je viens de faire plus haut à savoir déclarer et insérer des éléments dans un tableau:
3- Déclaration + insertion
La notation []
autorise en effet l'écriture d'éléments entre les deux crochets ce qui permet de déclarer et d'insérer dans la même instruction.
Bonus
La longueur d'un tableau est le nombre d'éléments qu'il contient. Ainsi, le tableau de l'exemple 3 a une longueur égale à 2, le tableau de l'exemple 2 a une longueur de 8. Un tableau vide a donc une longueur de 0. Il est cependant possible de déclarer un tableau ayant une longueur supérieure à 0, mais ne comportant "aucun" élément.
4- À ne pas reproduire !
L'idée est là, mais non plus sérieusement:
5- Déclaration d'un tableau vide de longueur n
Le tableau déclaré ainsi sera rempli avec 2 valeurs undefined
(mon exemple 4 n'était pas si naze au final). Il est rempli avec deux éléments qui symbolisent l'absence de valeur, il n'est donc pas considéré comme vide...
Parcourir un tableau
Dans cette partie, je vais poser un contexte. J'ai un tableau qui contient 10 éléments, des chaînes de caractères. J'aimerais appeler une fonction plusieurs fois, en passant à chaque appel un élément du tableau et ainsi, appeler la fonction avec tous les éléments ! En gros, j'aimerais appeler 10 fois une fonction qui prendra à chaque fois un argument: un élément du tableau !
6- La fonction à appeler
Parcourir un tableau, c'est accéder aux éléments qu'il contient. On a pour ça l'écriture que vous connaissez déjà sûrement déjà, myArray[x]
x étant l'indice de l'élément auquel on veut accéder. L'indice est compris entre 0 et la longueur du tableau moins 1; pour un tableau de 10 éléments, les indices disponibles vont donc de 0 à 9. Je pense que vous l'aurez compris, écrire à la main tous les myArray[0]
, myArray[1]
... c'est long et pénible...
Sachant cela, l'approche la plus naïve est la suivante:
7- Accès avec une boucle
for
Sur cet exemple, j'ai utilisé une boucle for
qui permet d'itérer tant de fois que les conditions écrite sur la première ligne sont respectée. Ici, on indique que l'on démarre le compte à 0, qu'on rentre dans la boucle tant que le compte est strictement inférieur à la longueur du tableau et qu'à chaque fin de boucle, on augmente le compte de 1. C'est la méthode la plus connue et que tout développeur a au moins utilisé une fois !
L'usage de la solution avec la boucle for
a tellement été utilisée que Javascript (pas le langage, mais la team qui travaille sur la spécification du langage) a mis à disposition une syntaxe spécialement faite pour les objets itérables, et comme les tableaux sont des objets itérables, nous pouvons utiliser cette nouvelle syntaxe introduite.
8- Accès avec une boucle
for..of
La boucle for..of
va permettre de mettre chaque élément du tableau dans une variable que j'ai appelé ici element
. Il n'est pas question d'utiliser directement myArray
ici pour accéder à l'élément courant du tableau mais juste la variable que l'on spécifie dans le for..of. Je préfère cette technique à la précédente pour les raisons suivantes:
- Pas besoin de réfléchir aux conditions d'itération, la boucle s'arrête d'elle-même, cette technique est donc plus sécurisée.
- La syntaxe est plus concise, on ne fait pas intervenir de compteur.
- Elle permet de montrer aux potentiels recruteurs que vous utilisez les mécaniques récentes du langage, c'est toujours un plus!
Bon, admettons qu'en plus de l'élément du tableau, on a aussi besoin de son index. Le code de l'exemple 8 ne permet pas d'avoir l'index, il n'est donc pas valable pour cette problématique. La solution, c'est le forEach
.
9- Accès aux éléments avec la méthode
.forEach
Ici, on utilise une méthode propre à l'objet Array
. Elle permet l'itération sur tous les éléments du tableau et attend en argument une fonction prenant 1 à 3 arguments. Ces arguments sont dans l'ordre:
- L'élément courant
- L'index de l'élément courant
- Le tableau auquel l'élément appartient (donc bon dans 100% des cas le tableau de base quoi)
Bonus
Il existe un moyen, fancy, luxueux, big brain d'accéder à des éléments d'un tableau quand on a une idée de ce qu'il contient à peu prêt. Admettons une fonction qui nous retourne un tableau de deux éléments. S'il se trouve, bizarrement, que ces deux éléments sont un nom et un prénom que l'on va utiliser plus tard dans le code, on peut se permettre de faire ça:
10- Déstructuration
Cette technique s'appelle la déstructuration. Elle permet d'assigner des éléments d'un tableau à une variable nommée ! Beaucoup plus sympathique d'écrire firstName
dans le code plutôt que de faire référence à myArray[1]
.
Fusionner des tableaux
Il arrive parfois que l'on ai à fusionner un ou plusieurs tableaux en un seul, afin de pouvoir traiter leur contenu dans un seul et même traitement. Pour cela, rien de bien compliqué ici:
11- Fusion de deux tableaux avec la méthode
.concat
La méthode .concat()
peut prendre en argument un ou plusieurs tableaux ce qui permet de les fusionner dans la même instruction. Cette méthode renvoie un tout nouveau tableau: il ne modifie pas le tableau que l'on utilise pour appeler la méthode: on dit alors que concat
ne mute pas (du verbe muter), le tableau initial !
Il existe une nouvelle façon récemment introduite pour créer un tableau à partir des éléments d'un ou plusieurs tableaux:
12- Concaténation avec le spread operator
J'ai utilisé une syntaxe particulière ici: les ...
. Il s'agit du spread operator, syntaxe de décomposition en français. Il s'utilise sur les tableaux (mais pas que!) et permet de faire référence à chaque élément du tableau séparément. Ainsi, ces deux écritures sont équivalentes:
13- Écritures équivalentes
Pour plus d'informations sur le spread operator: cliquez ici
Rechercher un élément
Un des cas d'utilisation le plus répandu concernant les tableaux est la recherche d'un élément spécifique à l'intérieur.
Prenons par exemple un tableau qui garde plusieurs objets représentant des personnes:
14- Tableau de personnes
Admettons le scénario suivant: on aimerait récupérer le profil de l'utilisateur "Christopher".
La première approche est la suivante:
15- Recherche à l'aide d'une structure
for..of
On utilise la boucle de parcours for..of
afin de vérifier le prénom de chaque profil et lorsque l'on tombe sur celui recherché, on l'affecte à une variable plus haut.
Javascript, encore une fois, nous donne la possibilité d'effectuer cette opération avec une syntaxe encore plus concise !
16- Recherche avec
.find
.find()
est une méthode offerte par l'objet Array (comme .concat()
ou .forEach()
) qui prend en argument une fonction, le prédicat, qui va s'appliquer sur tous les éléments du tableau. Le prédicat doit retourner une valeur booléenne (true
ou alors false
) qui indique si l'élément que l'on recherche dans le tableau est le bon ! Lorsque le prédicat retourne donc true
l'élément du tableau passé au prédicat est celui qui est retourné dans la variable christopherProfile
Dans les deux exemples ici, si l'élément recherché n'existait pas dans le tableau, la valeur de la variable christopherProfile
serait undefined
.
Vérifier ce que contient le tableau
Il est évidemment d'usage courant d'aller vérifier ce que contient un tableau. Ici, on a deux manières de la faire. Ces deux méthodes vont renvoyer un booléen qui indiquera si l'élément recherché est bel et bien dans le tableau.
La première méthode est celle-ci:
17- Vérification de contenance avec
.includes
.includes()
prend en argument l'exact élément recherché. C'est une méthode utile si l'on connaît l'élément exact (et j'insiste sur le exact), que l'on recherche. La seconde méthode est plus permissive dans la mesure où il est possible de rechercher si un élément dans le tableau correspond à un prédicat.
18- Vérification de contenance avec
.some
.some()
prend en argument une fonction qui sert de prédicat, qui prendra elle-même en argument les éléments du tableau un à un et qui renverra une valeur booléenne. Si aucun élément du tableau passé à la fonction n'a retourné true
, alors .some()
retournera false
mais si au moins un élément du tableau matche, .some()
retournera true
.
Le fait que .some()
prenne en argument un prédicat, en fait une méthode beaucoup plus puissante que .includes()
qui ne test au final qu'une égalité STRICTE entre l'élément passé en argument et les éléments du tableau. De ce fait, .includes()
est a utiliser avec parcimonie, car des erreurs sont vite arrivées:
19- Des objets identiques mais en réalité différents !
Dans cet exemple, l'objet dans la variable myValue
n'est pas strictement égal à {name: 'chris'}
(ils ont la même valeur, mais il ne s'agit pas du même objet en mémoire) et donc .includes()
retourne false
.
Conclusion: utilisez .some()
Filtrer les éléments du tableau
Quand on ne connaît pas exactement les éléments d'un tableau et qu'on aimerait en récupérer une partie qui correspondent à un critère particulier, on fait appel au filtrage !
20- Première approche de filtrage
Dans cet exemple, j'ai un tableau de noms et j'aimerais récupérer uniquement les noms qui commencent par la lettre c. Pour parvenir à ce résultat-là, je parcours mon tableau et je teste si l'élément courant commence par la lettre c. Si c'est le cas, je mets l'élément dans un nouveau tableau ainsi de suite...
Bon, il existe encore une fois un moyen plus classe de faire cette opération.
21- Filtrage avec
.filter
.filter()
prend en argument un prédicat qui va tester tous les éléments du tableau et mettre dans un nouveau tableau les éléments qui match avec le prédicat, tout simplement. Le traitement se fait en une seule ligne.
Transformer des éléments du tableau
Les opérations les plus complexes, mais rien de sorcier, sont dans cette section. Il peut parfois arriver que l'on ai besoin de transformer le tableau... en quelque chose d'autre. Ici, on a deux cas:
- On veut modifier les éléments d'un tableau. C'est le plus simple, on entre avec un tableau de n éléments, on finit avec un tableau de n éléments, la seule différence est ce quelque chose a changé avec ces éléments !
- On veut prendre le tableau et en ressortir quelque chose de totalement différent, un tout autre type de donnée. Ici c'est le freestyle complet, TOUT est possible !
Pour le premier cas, on a la méthode .map()
qui prend en argument une fonction que je vais appeler le transformateur. Cette fonction va prendre en argument l'élément courant du tableau et va retourner un nouvel élément, modifié, qui prendra la place de l'élément courant. Prenons la liste des prénoms précédente: pour les afficher dans mon site, j'aimerais les passer en majuscule pour une raison obscure:
22- Transformation avec
.map
Le fonctionnement est plutôt simple et les possibilités sont énormes !
Bon pour le second cas, admettons que je doive former une phrase avec tout ces prénoms comme par exemple "Je sors aujourd'hui avec chris, christine, christian, noah". On va utiliser un outil un peu overkill, mais pour l'exemple !
23- Transformation avec
.reduce
On utilise ici .reduce()
qui est une méthode des tableaux bien particulière. Elle permet de transformer un tableau en une toute autre valeur en utilisant un accumulateur.
Elle prend deux arguments.
Le premier est une fonction de callback qui va s'exécuter sur tous les éléments du tableau un à un, en prenant 3 arguments (2 obligatoires et un optionnel) et en retournant toujours l'accumulateur. Le premier est ce fameux accumulateur. C'est une valeur persistante entre les différentes exécutions de la fonction qui va représenter ce que l'on va retourner à l'issue de la méthode .reduce()
. Le second paramètre est l'item courant du tableau et le troisième (que je n'utilise pas dans l'exemple plus haut) est l'index de l'item dans le tableau.
Le dernier argument du .reduce()
est la valeur initiale de l'accumulateur (dans l'exemple, "Je sors aujourd'hui avec")...
La méthode .reduce()
est plus complexe à appréhender dans son mécanisme, mais il s'agit d'une méthode très populaire.
Le moyen le plus simple d'intégrer ces petits tips sur les arrays est bien évidemment la pratique. Ce sont des réflexes qui se construisent, le fait de penser à intégrer ces petits bouts de code quand une situation se présente ! N'hésitez pas à échanger en commentaires sur d'éventuelles améliorations de ce dont j'ai parlé ici ! Merci pour votre temps et à bientôt.
Tous les exemples sont disponibles dans le fichier JS sur ce gist Github
Merci à mes relecteur.rice.s: Eunice, Ibrahima, Anaël.
Crédit photo de couverture: https://unsplash.com/@tracycodes
Posted on July 15, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.