Ces trois fonctions sont utiles pour parcourir une liste (ou un tableau) et effectuer une sorte de transformation ou de calcul. Cela produira alors une nouvelle liste ou le résultat du calcul effectué sur la liste précédente.

Les types

Avant de plonger dans map, filter et reduce, configurons la liste.

 1const enum House {
 2  Gryffindor = "Gryffindor",
 3  Hufflepuff = "Hufflepuff",
 4  Ravenclaw = "Ravenclaw",
 5  Slytherin = "Slytherin"
 6}
 7type Wizard = {
 8  name: string;
 9  house: House;
10  points: number;
11};

types.ts
Chaque objet de l’assistant a un nom, une maison et le nombre de points qu’il a gagnés pour sa maison. Déclarons un groupe de magiciens et mettons-les dans une liste.

 1const HarryPotter: Wizard = {
 2  name: "Harry Potter",
 3  house: House.Gryffindor,
 4  points: 40
 5};
 6const HermioneGranger: Wizard = {
 7  name: "Hermione Granger",
 8  house: House.Gryffindor,
 9  points: 140
10};
11const DracoMalfoy: Wizard = {
12  name: "Draco Malfoy",
13  house: House.Slytherin,
14  points: -20
15};
16const TaylorSwift: Wizard = {
17  name: "Taylor Swift",
18  house: House.Slytherin,
19  points: 100
20};
21const LinManuelMiranda: Wizard = {
22  name: "Lin Manuel Miranda",
23  house: House.Slytherin,
24  points: 5000
25};
26const CedricDiggory: Wizard = {
27  name: "Cedric Diggory",
28  house: House.Hufflepuff,
29  points: 12
30};
31const SallyPerks: Wizard = {
32  name: "Sally Perks",
33  house: House.Hufflepuff,
34  points: 15
35};
36const LunaLovegood: Wizard = {
37  name: "Luna Lovegood",
38  house: House.Ravenclaw,
39  points: 100
40};
41const ChoChang: Wizard = {
42  name: "Cho Chang",
43  house: House.Ravenclaw,
44  points: 100
45};
46const wizards: Wizard[] = [
47  HarryPotter,
48  HermioneGranger,
49  DracoMalfoy,
50  LinManuelMiranda,
51  TaylorSwift,
52  CedricDiggory,
53  SallyPerks,
54  LunaLovegood,
55  ChoChang
56];

wizards.ts

Map

Maintenant que nous avons la base, allons-y. La première fonction est la plus simple, map. Map itère (ou boucle) sur une liste, applique une fonction à chaque élément de cette liste, puis renvoie une nouvelle liste d’éléments transformés. Regardons un exemple.

1const wizardNames = wizards.map(wizard => wizard.name);

wizard-names.ts

Cette fonction parcourt la liste des assistants, obtient leur nom et le place dans un nouveau tableau. Le résultat de ceci ressemble à ceci.

 1[
 2  "Harry Potter",
 3  "Hermione Granger",
 4  "Draco Malfoy",
 5  "Lin Manuel Miranda",
 6  "Taylor Swift",
 7  "Cedric Diggory",
 8  "Sally Perks",
 9  "Luna Lovegood",
10  "Cho Chang"
11];

Dans cet exemple, nous utilisions une fonction lambda (ou fonction anonyme), mais nous pouvons également utiliser une fonction nommée.

1function wizardToString({ name, house, points }: Wizard) {
2  return `${name}, ${house}, ${points}`;
3}
4const wizardStrings = wizards.map(wizardToString);

wizardToString.ts

Dans cet exemple, nous avons une fonction appelée wizardToString que nous transmettons directement au map. Il retournera alors une nouvelle liste qui ressemble à ceci.

 1[
 2  "Harry Potter, Gryffindor, 40",
 3  "Hermione Granger, Gryffindor, 140",
 4  "Draco Malfoy, Slytherin, -20",
 5  "Lin Manuel Miranda, Slytherin, 5000",
 6  "Taylor Swift, Slytherin, 100",
 7  "Cedric Diggory, Hufflepuff, 12",
 8  "Sally Perks, Hufflepuff, 15",
 9  "Luna Lovegood, Ravenclaw, 100",
10  "Cho Chang, Ravenclaw, 100"
11];

Filter

Le filter se comporte comme un map dans la mesure où il itère sur la liste, mais au lieu de transformer chaque élément, il transforme la liste entière. Le filter prend une fonction qui renvoie true ou false ou un prédicat. Il renvoie ensuite une nouvelle liste avec des éléments où le prédicat renvoie true. Regardons un exemple.

1const slytherins = wizards.filter(wizard => wizard.house === House.Slytherin);

slytherins.ts

Dans cet exemple, nous filtrons par-dessus la liste et n’incluons que les sorciers qui se trouvent dans la maison Serpentard. Le résultat serait ceci.

1[
2  { name: "Draco Malfoy", house: "Slytherin", points: -20 },
3  { name: "Lin Manuel Miranda", house: "Slytherin", points: 5000 },
4  { name: "Taylor Swift", house: "Slytherin", points: 100 }
5];

En passant, Taylor et Lin sont deux des Serpentards les plus acclamés de notre époque.

Comme avec map, nous n’avons pas besoin d’utiliser un lambda , nous pouvons également utiliser une fonction prédéfinie.

1function isWinner({ points }: Wizard) {
2  return points > 0;
3}
4function isLoser(wizard: Wizard) {
5  return !isWinner(wizard);
6}
7const winners = slytherins.filter(wizard => wizard.points > 0);
8const losers = slytherins.filter(wizard => wizard.points <= 0);

winners-losers.ts

Dans cet exemple, nous faisons deux listes, la liste des Serpentards ayant gagné des points (gagnants) et la liste des Serpentards ayant perdu des points (perdants). Nous pouvons voir ces résultats ci-dessous.

1const winnersResult = [
2  { name: "Lin Manuel Miranda", house: "Slytherin", points: 5000 },
3  { name: "Taylor Swift", house: "Slytherin", points: 100 }
4];
5const losersResult = [
6  { name: "Draco Malfoy", house: "Slytherin", points: -20 }
7];

Reduce

Nous arrivons maintenant à la fonction la plus intéressante, reduce. Reduce itère sur une liste et produit une valeur unique. Regardons un exemple.

Supposons que nous voulions obtenir le nombre total de points pour tous les assistants. Nous pouvons utiliser réduire pour faire cela.

1const totalPoints = wizards.reduce(
2  (accumulator, { points }) => accumulator + points,
3  0
4);

Que se passe t-il ici? Bien réduire est une fonction qui prend deux arguments, une fonction et une valeur initiale pour l’accumulateur. L’accumulateur est le nom de la chose réduire les rendements. Dans ce cas, nous commençons le compte de points à 0.

Maintenant, la fonction prend l’état actuel de l’accumulateur et de l’élément dans la liste qu’il est supposé traiter. Pour le premier assistant, il passera 0 pour l’accumulateur. Cette fonction retourne ensuite accumulator + points. Cela finira par résumer tous les points. Si vous êtes curieux, le résultat est 5487.

Maintenant, l’accumulateur peut être n’importe quoi, on peut même utiliser réduire pour produire un objet. Regardons un exemple où nous additionnons les points pour chaque maison.

1const pointsPerHouse = wizards.reduce((acc, { house, points }) => {
2  if (!acc[house]) {
3    acc[house] = 0;
4  }
5  acc[house] += points;
6  return acc;
7}, {});

points-per-house.ts

Dans ce cas, nous initialisons notre accumulateur ou acc avec {}. Ensuite, pour chaque assistant, nous appelons une fonction qui ajoute le nombre de points qu’il a gagnés pour sa maison. Si vous êtes curieux, ce résultat ressemble à ceci.

1{
2  Gryffindor: 180,
3  Slytherin: 5080,
4  Hufflepuff: 27,
5  Ravenclaw: 200
6};

Regardons un autre exemple, disons que nous voulons le meilleur assistant pour chaque maison. Nous pouvons modifier notre fonction précédente pour utiliser le meilleur assistant pour chaque maison.

 1const bestPerHouse = wizards.reduce((acc, wizard) => {
 2  const { house, points } = wizard;
 3  if (!acc[house]) {
 4    acc[house] = wizard;
 5  }
 6  if (acc[house].points < points) {
 7    acc[house] = wizard;
 8  }
 9  return acc;
10}, {});

Si vous êtes curieux, le résultat est le suivant.

1{
2  Gryffindor: { name: "Hermione Granger", house: "Gryffindor", points: 140 },
3  Slytherin: { name: "Lin Manuel Miranda", house: "Slytherin", points: 5000 },
4  Hufflepuff: { name: "Sally Perks", house: "Hufflepuff", points: 15 },
5  Ravenclaw: { name: "Luna Lovegood", house: "Ravenclaw", points: 100 }
6};

Juste un peu plus de plaisir maintenant, nous pouvons utiliser Object.values pour transformer cet map.

1const bestNamesPerHouse = Object.values(bestPerHouse).map(wizardToString);
2[
3  "Hermione Granger, Gryffindor, 140",
4  "Lin Manuel Miranda, Slytherin, 5000",
5  "Sally Perks, Hufflepuff, 15",
6  "Luna Lovegood, Ravenclaw, 100"
7];

best-names-per-house.ts

Maintenant, nous avons de beaux noms pour la meilleure personne dans chaque maison.