Dans cet article nous allons voir trois méthodes JavaScript indispensables pour réaliser des traitements sur des tableaux. Si vous en avez marre de galérer avec vos boucles while, vos boucles for et que vous aimez un peu trop les forEach, je vais vous montrer les alternatives élégantes et performantes pour significativement améliorer votre code. Sans plus attendre, partons à la rencontre des power rangers du JavaScript.
Données d’exemple
Afin de simplifier la compréhension, nous prendrons le tableau suivant pour illustrer les différents exemples.
const employees: Employee[] = [
{
id: 1,
name: "Patrick",
salary: 42000,
},
{
id: 2,
name: "Berth",
salary: 44000,
},
{
id: 3,
name: "Alexandre",
salary: 38000,
},
];
1. Force Bleu : filter
Lorsque l’on manipule des tableaux, l’une des opérations les plus courantes est le filtre. Filtrer un tableau permet de ne garder que les éléments qui nous intéressent et de supprimer les éléments indésirables.
Prenons un exemple simple, nous voulons filtrer le tableau employees pour ne garder que les employés qui gagnent plus de 40000. Regardons les deux approches possibles pour arriver au résultat.
Approche naïve
L’approche naïve serait de déclarer un tableau vide filteredEmployees. Ensuite, on parcourt les éléments du tableau employees. Chaque fois qu’un employé respecte la condition (salaire > 40000), il faut ajouter l’élément au tableau filteredEmployees. On obtient alors le tableau des employés gagnant plus de 40000.
const filteredEmployees: Employee[] = [];
employees.forEach((employee: Employee) => {
if (employee.salary > 40000) {
filteredEmployees.push(employee);
}
});
Equivalent avec la méthode filter
La méthode filter permet de filtrer un tableau afin de ne garder que les éléments qui respectent une condition.
Réimplémentons l’approche naïve avec la méthode filter.
const filteredEmployees = employees.filter((employee: Employee) => employee.salary > 40000);
Si on regarde ce code de plus près, on applique la méthode filter au tableau employees. Dans le corps de la méthode on vient mettre la condition (fonction callback). Ici, tous les employés gagnant plus de 40000 seront garder dans le tableau de retour. On obtient alors une copie filtrée de la liste employees.
Utiliser filter permet d’avoir un code plus court sans perdre du sens car la méthode explicite le traitement réalisé. Ainsi le code est plus facile à lire.
2. Force Rouge : map
Une autre opération courante est de devoir appliquer un traitement sur les éléments d’un tableau.
Prenons comme exemple la situation suivante. Nous voulons augmenter de 2000 le salaire de tous les employés.
Approche naïve
L’approche naïve est de déclarer un tableau vide updatedEmployees, ensuite de parcourir le tableau employee. Pour chacun des employees on vient faire une copie et on augmente le salaire. Enfin, on met la copie modifiée de l’employé dans le tableau updatedEmployees. On obtient alors le tableau des employés augmenté de 2000.
const updatedEmployees: Employee[] = [];
employees.forEach((employee: Employee) => {
const updatedEmployee = {
...employee,
salary: employee.salary + 2000,
};
updatedEmployees.push(updatedEmployee);
});
Equivalent avec la méthode map
La méthode map permet d’appliquer un traitement sur chaque élément d’un tableau.
Réimplémentons l’approche naïve avec la méthode map.
const updatedEmployees = employees.map((employee: Employee) => {
return {
...employee,
salary: employee.salary + 2000,
};
});
Si on regarde de plus, dans ce code on applique la méthode map sur employees afin d’effectué un traitement sur tous les éléments de ce tableau. Le traitement correspond à la fonction callback dans le corps de la méthode map. Ici on prend un employé, on lui ajoute 2000 sur son salaire puis on le renvoie. La méthode map renvoie une copie modifiée du tableau d’origine.
Utiliser la méthode map permet de modifier tous les éléments d’un tableau. de façon concise et simple. Pas besoin de créer de copie car cette dernière est renvoyée par la méthode à la fin du traitement. On obtient donc un code plus court et plus explicite car le traitement apparait dans le corps de la méthode.
3. Force Jaune : reduce
Il est fréquent de vouloir calculer une donnée sur les éléments d’un tableau.
Prenons pour exemple la situation suivante. Nous voulons calculer la somme des salaires des employés.
Approche naïve
Pour cela, une approche naïve pourrait être de déclarer une variable amount. Ensuite il faudrait parcourir le tableau employees et incrémenter amount avec le salaire des différents employés. Le code ci-dessous illustre cet exemple.
let amount: number = 0;
employee.forEach((employee: Employee) => {
amount += employee.salary;
});
Equivalent avec la méthode reduce
La méthode reduce permet de faire des calculs sur les éléments d’un tableau et de renvoyer une valeur que l’on appel accumulateur. La méthode reduce fait perdre une dimension en passant d’un tableau à une valeur.
const amount = employees.reduce((acc, employee) => acc += employee.salary, 0);
On obtient le même résultat en une seule ligne. Si on regarde le code, on applique la méthode reduce au tableau employees. On vient donc parcourir tous les employés un à un. Pour chaque employé, on incrémente l’accumulateur qui ici est la somme des salaires. Une fois le tableau parcourut en entier, l’accumulateur est renvoyé et affecte à amount.
Le code est ainsi beaucoup plus court, plus claire et plus explicite.
4. L’équipe au complète : La puissance de la programmation fonctionnelle
Il est possible d’utiliser les trois méthodes combinées afin de réaliser des traitements complexes.
Prenons comme exemple la situation suivante. Il faudrait augmenter les employées de 2000 euros puis calculer la sommes des salaires strictement supérieurs à 40000.
Ici on a trois opérations :
- Augmenter de 2000 chaque salaire
- Filtrer les employés qui gagnent plus de 40000
- Calculer la somme des salaires au dessus de 40000
const updatedEmployees: Employee[] = [];
// Augmenter de 2000 chaque salaire
employees.forEach((employee: Employee) => {
updatedEmployees.push({
...employee,
salary: employee.salary + 2000,
});
});
const filteredEmployees: Employee[] = [];
// Filtrer les employés qui gagnent plus de 40000
updatedEmployees.forEach((employee: Employee) => {
if (employee.salary > 40000) {
filteredEmployees.push(employee);
}
});
let amount: number = 0;
// Calculer la somme des salaires au dessus de 40000
filteredEmployees.forEach((employee: employee) => {
amount += employee.salary;
});
Maintenant comparons avec la solution utilisant la combinaison de map, filter et reduce.
const amount = employees.map((employee: Employee) => {
return {
...employee,
salary: employee.salary + 2000,
};
})
.filter((employee: Employee) => employee.salary > 40000)
.reduce((acc: number, employee: Employee) => acc + employee.salary, 0);
Voilà le résultat, la différence est incontestable. Comme nous le montre cet exemple, lorsqu’il s’agit de faire des traitements plus complexe, utiliser les méthodes map, filter et reduce permet de simplifier le code. On obtient un code qui est concis, facile à lire et sans ambiguïtés.
Conclusion
Nous avons vu dans cet article que l’on peut significativement se simplifier la vie en utilisant les méthodes javascript filter, map et reduce. Nous l’avons vu avec tous les exemples, ces méthodes apportent de la clarté et du contexte dans votre code.
“Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do”. Donald Knuth
Comme le dit si bien Donald Knuth, au lieu de dire à la machine ce que l’on veut qu’elle fasse, écrivons du code pour expliquer aux humains ce que l’on veut que la machine fasse.
Si vous voulez améliorer votre expérience de développeur et bénéficier des bien fait du clean code, n’hésitez plus, utilisez map, filter, reduce !
Top comments (1)
👌