Manipulation de tableaux avec JS
Tags: javascript, francais, french, array
Published: 2020-07-15 22:29:44

### 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.
![Déclaration d'un tableau](https://dev-to-uploads.s3.amazonaws.com/i/7a1vf1cc3d2m2soqsl8l.png)
> 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:

![Insertion d'éléments dans un tableau](https://dev-to-uploads.s3.amazonaws.com/i/dk3zbcbhpdm0ffjvxfrr.png)
> 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:

![Déclaration + insertion](https://dev-to-uploads.s3.amazonaws.com/i/01jr4d84hl0jv5fk6v5u.png)
> 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.

![À ne pas reproduire !](https://dev-to-uploads.s3.amazonaws.com/i/n17y8z8g02ez65rhx03t.png)
> 4- À ne pas reproduire !

L'idée est là, mais non plus sérieusement:

![Déclaration d'un tableau vide de longueur n](https://dev-to-uploads.s3.amazonaws.com/i/2ogz62dxvkj3z52oz1cp.png)
> 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 !

![La fonction à appeler](https://dev-to-uploads.s3.amazonaws.com/i/vw0ficie8f3ebhdehugj.png)
> 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:

![Accès avec une boucle for](https://dev-to-uploads.s3.amazonaws.com/i/r80sm9h844nmfago4d4r.png)
> 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](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Les_protocoles_iteration), et comme les tableaux sont des objets itérables, nous pouvons utiliser cette nouvelle syntaxe introduite.

![Accès avec une boucle for..of](https://dev-to-uploads.s3.amazonaws.com/i/iqnwo9zq3cguenyihmn2.png)
> 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`.

![Accès aux éléments avec la méthode forEach](https://dev-to-uploads.s3.amazonaws.com/i/20izfxj2x8gpom6mwmzq.png)
> 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:

1. L'élément courant
2. L'index de l'élément courant
3. 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:

![Destructuration](https://dev-to-uploads.s3.amazonaws.com/i/zqfz2j6lop1vx9myj708.png)
> 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:

![Fusion de deux tableaux avec la méthode concat](https://dev-to-uploads.s3.amazonaws.com/i/c50lcx3c50ehzrc9pp07.png)
> 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:

![Concaténation avec le spread operator](https://dev-to-uploads.s3.amazonaws.com/i/w3h2jjenyp6nhf5bqact.png)
> 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:

![Écritures équivalentes](https://dev-to-uploads.s3.amazonaws.com/i/j13tyuwm7bxgyut2dht2.png)
> 13- Écritures équivalentes

Pour plus d'informations sur le spread operator: [cliquez ici](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Opérateurs/Syntaxe_décomposition)

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

![Tableau de personnes](https://dev-to-uploads.s3.amazonaws.com/i/ydkkcb0pdu67r8wor6jn.png)
> 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:

![Recherche à l'aide d'une structure for..of](https://dev-to-uploads.s3.amazonaws.com/i/lzdt8i5e7lgy1ff05a06.png)
> 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 !

![Recherche avec .find](https://dev-to-uploads.s3.amazonaws.com/i/n7ny9nwc1conuwerxua2.png)
> 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:

![Vérification de contenance avec .includes](https://dev-to-uploads.s3.amazonaws.com/i/d6jg6wj6le3tk8fsktmk.png)
> 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.

![Vérification de contenance avec .some](https://dev-to-uploads.s3.amazonaws.com/i/hf0b7tmekispqjq6o0hb.png)
> 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:

![Des objets identiques mais en réalité différents !](https://dev-to-uploads.s3.amazonaws.com/i/euzjyk3xhhvrm3ndzmb1.png)
> 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 !

![Première approche de filtrage](https://dev-to-uploads.s3.amazonaws.com/i/hp7lgtukneljw0ya3tsc.png)
> 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.


![Filtrage avec `.filter`](https://dev-to-uploads.s3.amazonaws.com/i/8soa871q4999cvabse8g.png)
> 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:

1. 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 !
2. 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:

![Transformation avec map](https://dev-to-uploads.s3.amazonaws.com/i/ctpbnd6mnx6fay65s2ec.png)
> 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 !

![Transformation avec `.reduce`](https://dev-to-uploads.s3.amazonaws.com/i/q0zsn8jgij6yn3jz18ln.png)
> 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](https://gist.github.com/Christopher2K/0cceda49f8f85b874cc07764c5bc2fbd)
Merci à mes relecteur.rice.s: Eunice, Ibrahima, Anaël.

Crédit photo de couverture: [https://unsplash.com/@tracycodes](https://unsplash.com/@tracycodes)