Cours JavaScript et TypeScript · Module 2: Fonctions, tableaux et objets
Les méthodes de base des tableaux en JavaScript
Dans cette leçon3
Bienvenue de retour à Jurassic Park ! Dans la leçon précédente, tu as appris les bases des tableaux en JavaScript. Nous allons maintenant plonger dans les méthodes de base des tableaux, essentielles pour le travail quotidien avec les données. Ces méthodes te permettent d'ajouter, de retirer et de manipuler des éléments dans les tableaux, ce qui est crucial pour gérer l'inventaire des dinosaures, planifier les repas et organiser le personnel du parc.
Modifier les tableaux - les méthodes mutantes
Commençons par examiner les méthodes qui modifient le tableau original. On les appelle des méthodes mutantes.
1. push() - Ajouter des éléments à la fin d'un tableau
La méthode push() ajoute un ou plusieurs éléments à la fin d'un tableau et renvoie la nouvelle longueur du tableau :
1// Gestion des espèces de dinosaures dans notre enclos
2const dinoEnclosure = ["T-Rex", "Velociraptor"];
3
4// Ajout d'une nouvelle espèce de dinosaure
5dinoEnclosure.push("Dilophosaurus");
6console.log(dinoEnclosure); // ["T-Rex", "Velociraptor", "Dilophosaurus"]
7
8// Ajout de plusieurs espèces à la fois
9const newLength = dinoEnclosure.push("Gallimimus", "Compsognathus");
10console.log(dinoEnclosure);
11// ["T-Rex", "Velociraptor", "Dilophosaurus", "Gallimimus", "Compsognathus"]
12console.log(`Nombre actuel d'espèces dans l'enclos : ${newLength}`); // 5Quand utiliser push() :
- Quand tu dois ajouter un ou plusieurs éléments à la fin d'un tableau
- Quand tu veux connaître la nouvelle longueur du tableau après l'ajout d'éléments
- Quand l'ordre des éléments compte et que le nouvel élément doit aller à la fin
2. pop() - Retirer le dernier élément
La méthode pop() retire le dernier élément d'un tableau et renvoie cet élément :
1// Liste des dinosaures dans notre enclos
2const dinoEnclosure = ["T-Rex", "Velociraptor", "Dilophosaurus", "Compsognathus"];
3
4// Déplacement du dernier dinosaure vers un nouvel enclos
5const removedDino = dinoEnclosure.pop();
6console.log(`Dinosaure déplacé : ${removedDino}`); // "Compsognathus"
7console.log("Dinosaures restants :", dinoEnclosure); // ["T-Rex", "Velociraptor", "Dilophosaurus"]
8
9// On peut continuer à en retirer
10const anotherRemovedDino = dinoEnclosure.pop();
11console.log(`Autre dinosaure déplacé : ${anotherRemovedDino}`); // "Dilophosaurus"
12console.log("Contenu actuel de l'enclos :", dinoEnclosure); // ["T-Rex", "Velociraptor"]Quand utiliser pop() :
- Quand tu dois retirer le dernier élément d'un tableau
- Quand tu as besoin de récupérer la valeur de l'élément retiré
- Quand tu implémentes des structures de données de type pile (LIFO - Last In, First Out)
3. unshift() - Ajouter des éléments au début
La méthode unshift() ajoute un ou plusieurs éléments au début d'un tableau et renvoie la nouvelle longueur du tableau :
1// File d'attente des dinosaures en attente d'examen
2const dinoQueue = ["Velociraptor", "Triceratops"];
3
4// Ajout prioritaire du T-Rex en tête de file
5dinoQueue.unshift("T-Rex");
6console.log("File actuelle :", dinoQueue); // ["T-Rex", "Velociraptor", "Triceratops"]
7
8// Ajout de plusieurs dinosaures à la fois en tête de file
9const newQueueSize = dinoQueue.unshift("Brachiosaurus", "Stegosaurus");
10console.log("File actuelle :", dinoQueue);
11// ["Brachiosaurus", "Stegosaurus", "T-Rex", "Velociraptor", "Triceratops"]
12console.log(`Nombre de dinosaures dans la file : ${newQueueSize}`); // 5Quand utiliser unshift() :
- Quand tu veux ajouter un élément au début d'un tableau
- Quand tu implémentes des files de priorité où les éléments les plus prioritaires vont en tête
- Quand tu dois connaître la nouvelle longueur du tableau
4. shift() - Retirer le premier élément
La méthode shift() retire le premier élément d'un tableau et renvoie cet élément :
1// File d'attente des dinosaures en attente d'examen
2const dinoQueue = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"];
3
4// Récupération du premier dinosaure pour l'examen
5const nextDino = dinoQueue.shift();
6console.log(`Examen du dinosaure : ${nextDino}`); // "T-Rex"
7console.log("File restante :", dinoQueue); // ["Velociraptor", "Triceratops", "Stegosaurus"]
8
9// Traitement du dinosaure suivant
10const anotherDino = dinoQueue.shift();
11console.log(`Dinosaure suivant à examiner : ${anotherDino}`); // "Velociraptor"
12console.log("État actuel de la file :", dinoQueue); // ["Triceratops", "Stegosaurus"]Quand utiliser shift() :
- Quand tu dois retirer et récupérer le premier élément d'un tableau
- Quand tu implémentes des files d'attente (FIFO - First In, First Out)
- Quand tu traites les éléments dans l'ordre où ils ont été ajoutés
5. splice() - Modifier des éléments à n'importe quelle position
La méthode splice() modifie le contenu d'un tableau en retirant, remplaçant ou ajoutant des éléments. Elle est extrêmement polyvalente car elle permet de modifier le tableau à n'importe quelle position.
Syntaxe de base : array.splice(startIndex, deleteCount, item1, item2, ...) :
startIndex: l'index à partir duquel commencer la modificationdeleteCount: le nombre d'éléments à retireritem1, item2, ...: (optionnel) les éléments à ajouter
5.1. Retirer des éléments avec splice()
1// Liste des espèces de dinosaures dans le parc
2const dinosaurs = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus", "Brachiosaurus"];
3
4// Retire 2 éléments à partir de l'index 1 (le deuxième élément)
5const removedDinos = dinosaurs.splice(1, 2);
6console.log("Dinosaures retirés :", removedDinos); // ["Velociraptor", "Triceratops"]
7console.log("Dinosaures restants :", dinosaurs); // ["T-Rex", "Stegosaurus", "Brachiosaurus"]5.2. Remplacer des éléments avec splice()
1// Liste des espèces de dinosaures
2const dinosaurs = ["T-Rex", "Dilophosaurus", "Triceratops", "Stegosaurus"];
3
4// Remplace Dilophosaurus par Velociraptor
5const replaced = dinosaurs.splice(1, 1, "Velociraptor");
6console.log("Dinosaure remplacé :", replaced); // ["Dilophosaurus"]
7console.log("Liste actuelle :", dinosaurs); // ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"]
8
9// Remplace plusieurs éléments à la fois
10dinosaurs.splice(2, 2, "Brachiosaurus", "Ankylosaurus", "Parasaurolophus");
11console.log("Nouvelle composition :", dinosaurs);
12// ["T-Rex", "Velociraptor", "Brachiosaurus", "Ankylosaurus", "Parasaurolophus"]5.3. Ajouter des éléments sans en retirer
1// Liste des espèces de dinosaures
2const dinosaurs = ["T-Rex", "Velociraptor"];
3
4// Ajoute une nouvelle espèce à l'index 1 (entre T-Rex et Velociraptor)
5dinosaurs.splice(1, 0, "Dilophosaurus", "Compsognathus");
6console.log(dinosaurs); // ["T-Rex", "Dilophosaurus", "Compsognathus", "Velociraptor"]Quand utiliser splice() :
- Quand tu dois modifier un tableau à une position précise, pas seulement à la fin ou au début
- Quand tu dois retirer et/ou ajouter des éléments simultanément
- Quand tu veux remplacer une section d'un tableau par de nouvelles valeurs
6. sort() - Trier un tableau
La méthode sort() trie les éléments d'un tableau sur place et renvoie le tableau trié :
1// Liste des dinosaures pour le repas
2const feedingList = ["Velociraptor", "T-Rex", "Dilophosaurus", "Gallimimus", "Compsognathus"];
3
4// Tri alphabétique
5feedingList.sort();
6console.log("Liste de nourrissage (ordre alphabétique) :", feedingList);
7// ["Compsognathus", "Dilophosaurus", "Gallimimus", "T-Rex", "Velociraptor"]
8
9// Tableau avec les tailles des dinosaures (en cm)
10const dinoSizes = [1200, 300, 800, 2000, 40];
11
12// Le tri par défaut traite les nombres comme des chaînes de caractères - ça ne fonctionnera pas correctement !
13dinoSizes.sort();
14console.log("Tailles mal triées :", dinoSizes);
15// Probablement : [1200, 2000, 300, 40, 800] - incorrect !
16
17// Tri numérique correct avec une fonction de comparaison
18dinoSizes.sort((a, b) => a - b);
19console.log("Tailles correctement triées (ordre croissant) :", dinoSizes);
20// [40, 300, 800, 1200, 2000]
21
22// Tri décroissant
23dinoSizes.sort((a, b) => b - a);
24console.log("Tailles triées par ordre décroissant :", dinoSizes);
25// [2000, 1200, 800, 300, 40]Trier des objets
1// Données des dinosaures pour le repas
2const dinosaurs = [
3 { name: "T-Rex", weight: 7000, priority: 1 },
4 { name: "Velociraptor", weight: 100, priority: 2 },
5 { name: "Triceratops", weight: 9000, priority: 3 },
6 { name: "Gallimimus", weight: 450, priority: 4 }
7];
8
9// Tri par priorité de repas
10dinosaurs.sort((a, b) => a.priority - b.priority);
11console.log("Ordre des repas par priorité :");
12dinosaurs.forEach(dino => console.log(`${dino.name} (priorité : ${dino.priority})`));
13
14// Tri par poids (le plus lourd en premier)
15dinosaurs.sort((a, b) => b.weight - a.weight);
16console.log("\nOrdre par poids (le plus lourd en premier) :");
17dinosaurs.forEach(dino => console.log(`${dino.name} (${dino.weight} kg)`));
18
19// Tri alphabétique par nom
20dinosaurs.sort((a, b) => a.name.localeCompare(b.name));
21console.log("\nDinosaures par ordre alphabétique :");
22dinosaurs.forEach(dino => console.log(`${dino.name}`));La méthode sort() accepte une fonction de comparaison optionnelle qui doit renvoyer :
- Une valeur négative si a doit être placé avant b
- Zéro si a et b sont équivalents du point de vue du tri
- Une valeur positive si a doit être placé après b
Quand utiliser sort() :
- Quand tu dois ordonner les éléments d'un tableau selon un critère précis
- Quand tu travailles avec des listes qui doivent être présentées dans un ordre spécifique
- Quand tu implémentes une fonctionnalité de tri dans une application
7. reverse() - Inverser l'ordre d'un tableau
La méthode reverse() inverse l'ordre des éléments d'un tableau et renvoie le tableau inversé :
1// Liste des dinosaures du plus vieux au plus jeune
2const dinosaursByAge = ["Brachiosaurus", "Stegosaurus", "Triceratops", "Velociraptor", "T-Rex"];
3
4// Inverse l'ordre pour aller du plus jeune au plus vieux
5dinosaursByAge.reverse();
6console.log("Du plus jeune au plus vieux :", dinosaursByAge);
7// ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus", "Brachiosaurus"]
8
9// Souvent utilisé en combinaison avec sort()
10const dinoHeights = [500, 900, 200, 1200, 350];
11// Tri décroissant en triant par ordre croissant puis en inversant
12dinoHeights.sort((a, b) => a - b).reverse();
13console.log("Hauteurs par ordre décroissant :", dinoHeights);
14// [1200, 900, 500, 350, 200]Quand utiliser reverse() :
- Quand tu dois inverser l'ordre des éléments d'un tableau
- Quand tu veux passer d'un ordre croissant à décroissant (ou l'inverse) après un tri
- Quand tu implémentes une fonctionnalité d'« ordre inversé » dans une interface utilisateur
8. fill() - Remplir un tableau avec une valeur
La méthode fill() remplit tous les éléments d'un tableau, d'un index de départ à un index de fin (exclu), avec une valeur spécifiée :
1// Préparation d'un tableau pour les relevés de température des dinosaures (10 relevés)
2const temperatures = new Array(10);
3
4// Remplissage avec une valeur par défaut (38.5 degrés Celsius)
5temperatures.fill(38.5);
6console.log("Températures par défaut :", temperatures);
7// [38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5]
8
9// Remplit seulement une partie du tableau
10temperatures.fill(39.2, 2, 5); // De l'index 2 (inclus) à 5 (exclu)
11console.log("Températures mises à jour :", temperatures);
12// [38.5, 38.5, 39.2, 39.2, 39.2, 38.5, 38.5, 38.5, 38.5, 38.5]
13
14// Utilisation avec un nouveau tableau et des index négatifs (comptés depuis la fin)
15const feedingSchedule = new Array(7).fill("Standard");
16feedingSchedule.fill("Portion supplémentaire", -3); // Les 3 derniers jours
17console.log("Plan de nourrissage de la semaine :", feedingSchedule);
18// ["Standard", "Standard", "Standard", "Standard", "Portion supplémentaire", "Portion supplémentaire", "Portion supplémentaire"]Quand utiliser fill() :
- Quand tu crées un nouveau tableau et dois le remplir avec une valeur initiale précise
- Quand tu dois remplacer tout ou partie des valeurs d'un tableau existant
- Quand tu initialises des tableaux pour stocker des données avec des valeurs par défaut
Application pratique des méthodes de base des tableaux
Maintenant, combinons les méthodes que nous avons apprises pour résoudre des scénarios plus pratiques dans notre Jurassic Park :
Exemple 1 : Système de gestion de la nourriture des dinosaures
1// Système de gestion de la nourriture des dinosaures
2const feedingSystem = {
3 // État du système
4 foodInventory: [],
5 feedingQueue: [],
6 feedingHistory: [],
7
8 // Ajout d'un nouvel approvisionnement
9 addFoodSupply: function(type, quantity, expirationDate) {
10 const supply = { type, quantity, expirationDate, addedOn: new Date() };
11 this.foodInventory.push(supply);
12
13 // Trie par date d'expiration (la plus proche en premier)
14 this.foodInventory.sort((a, b) =>
15 new Date(a.expirationDate) - new Date(b.expirationDate)
16 );
17
18 console.log(`Ajout de ${quantity}kg de nourriture "${type}" aux réserves.`);
19 return supply;
20 },
21
22 // Ajout d'un dinosaure à la file d'attente de repas
23 scheduleDinoFeeding: function(dinoId, dinoName, foodType, quantity, priority) {
24 const feedingRequest = {
25 dinoId,
26 dinoName,
27 foodType,
28 quantity,
29 priority,
30 scheduledAt: new Date()
31 };
32
33 if (priority === "high") {
34 // Ajoute en tête de file
35 this.feedingQueue.unshift(feedingRequest);
36 } else {
37 // Ajoute en fin de file
38 this.feedingQueue.push(feedingRequest);
39 }
40
41 console.log(`Repas planifié pour ${dinoName} (priorité : ${priority})`);
42 return this.feedingQueue.length;
43 },
44
45 // Récupération du prochain dinosaure à nourrir
46 getNextDinoToFeed: function() {
47 if (this.feedingQueue.length === 0) {
48 console.log("Tous les dinosaures sont nourris. File vide.");
49 return null;
50 }
51
52 const nextFeeding = this.feedingQueue.shift();
53 console.log(`Prochain à nourrir : ${nextFeeding.dinoName}`);
54 return nextFeeding;
55 },
56
57 // Distribution de la nourriture depuis l'entrepôt
58 dispenseFoodForDino: function(dinoFeeding) {
59 const { foodType, quantity, dinoName } = dinoFeeding;
60
61 // Recherche de l'approvisionnement adapté
62 let remainingQuantity = quantity;
63 const usedSupplies = [];
64
65 // Parcourt à partir de l'approvisionnement le plus ancien (expire le plus tôt)
66 for (let i = 0; i < this.foodInventory.length && remainingQuantity > 0; i++) {
67 const supply = this.foodInventory[i];
68
69 if (supply.type === foodType && supply.quantity > 0) {
70 // La quantité qu'on peut prendre de cet approvisionnement
71 const amountToTake = Math.min(remainingQuantity, supply.quantity);
72 supply.quantity -= amountToTake;
73 remainingQuantity -= amountToTake;
74
75 usedSupplies.push({
76 type: supply.type,
77 amount: amountToTake,
78 expirationDate: supply.expirationDate
79 });
80
81 // Si l'approvisionnement est vide, on le retire de l'inventaire
82 if (supply.quantity === 0) {
83 this.foodInventory.splice(i, 1);
84 i--; // Ajuste l'index après la suppression de l'élément
85 }
86 }
87 }
88
89 // Ajoute un enregistrement à l'historique des repas
90 const feedingRecord = {
91 ...dinoFeeding,
92 fedAt: new Date(),
93 suppliesUsed: usedSupplies,
94 fullyFed: remainingQuantity === 0
95 };
96
97 this.feedingHistory.push(feedingRecord);
98
99 if (remainingQuantity > 0) {
100 console.log(`ATTENTION : il manque ${remainingQuantity}kg de nourriture "${foodType}" pour ${dinoName} !`);
101 return false;
102 }
103
104 console.log(`${dinoName} a été nourri avec ${quantity}kg de nourriture "${foodType}".`);
105 return feedingRecord;
106 },
107
108 // Exécution d'un cycle complet de repas
109 processFeedingCycle: function(maxFeedings = 5) {
110 console.log("=== DÉBUT DU CYCLE DE REPAS ===");
111 let feedingsProcessed = 0;
112
113 // Traite un nombre défini de repas ou jusqu'à ce que la file soit vide
114 while (feedingsProcessed < maxFeedings && this.feedingQueue.length > 0) {
115 const nextDino = this.getNextDinoToFeed();
116
117 if (nextDino) {
118 const result = this.dispenseFoodForDino(nextDino);
119
120 if (!result) {
121 // Si le repas a échoué, déplace le dinosaure à la fin de la file
122 this.feedingQueue.push({
123 ...nextDino,
124 priority: "high", // Augmente la priorité pour le dinosaure non nourri
125 scheduledAt: new Date()
126 });
127 console.log(`${nextDino.dinoName} déplacé en fin de file avec une priorité haute.`);
128 }
129
130 feedingsProcessed++;
131 }
132 }
133
134 console.log(`=== FIN DU CYCLE DE REPAS (traités : ${feedingsProcessed}) ===`);
135 console.log(`Il reste ${this.feedingQueue.length} dinosaures dans la file`);
136 return feedingsProcessed;
137 },
138
139 // Rapport de l'état de l'inventaire
140 reportInventoryStatus: function() {
141 console.log("=== RAPPORT SUR L'ÉTAT DES STOCKS ===");
142
143 if (this.foodInventory.length === 0) {
144 console.log("L'entrepôt est vide ! Commande de nouvelles réserves de nourriture !");
145 return { isEmpty: true, totalQuantity: 0, types: [] };
146 }
147
148 // Regroupe les approvisionnements par type
149 const inventory = this.foodInventory.reduce((acc, supply) => {
150 if (!acc[supply.type]) {
151 acc[supply.type] = 0;
152 }
153 acc[supply.type] += supply.quantity;
154 return acc;
155 }, {});
156
157 // Calcule la quantité totale
158 const totalQuantity = Object.values(inventory).reduce((sum, qty) => sum + qty, 0);
159
160 console.log(`Réserve totale de nourriture : ${totalQuantity}kg`);
161 Object.entries(inventory).forEach(([type, qty]) => {
162 console.log(`- ${type}: ${qty}kg`);
163 });
164
165 // Vérifie les approvisionnements qui expirent bientôt (dans les 3 jours)
166 const today = new Date();
167 const threeDaysLater = new Date(today);
168 threeDaysLater.setDate(today.getDate() + 3);
169
170 const expiringSupplies = this.foodInventory.filter(supply =>
171 new Date(supply.expirationDate) <= threeDaysLater
172 );
173
174 if (expiringSupplies.length > 0) {
175 console.log("\nRéserves qui expirent dans les 3 jours :");
176 expiringSupplies.forEach(supply => {
177 console.log(`- ${supply.quantity}kg ${supply.type} (expiration : ${supply.expirationDate})`);
178 });
179 }
180
181 return {
182 isEmpty: false,
183 totalQuantity,
184 types: Object.keys(inventory),
185 inventory,
186 expiringSupplies
187 };
188 }
189};
190
191// Démonstration du système
192console.log("=== DÉMONSTRATION DU SYSTÈME DE GESTION DE LA NOURRITURE ===");
193
194// 1. Ajout d'approvisionnements
195feedingSystem.addFoodSupply("Viande", 500, "2023-07-15");
196feedingSystem.addFoodSupply("Plantes", 800, "2023-07-10");
197feedingSystem.addFoodSupply("Poisson", 200, "2023-07-05");
198feedingSystem.addFoodSupply("Viande", 300, "2023-07-20");
199
200// 2. Planification des repas
201feedingSystem.scheduleDinoFeeding("TRX-01", "Rex", "Viande", 150, "high");
202feedingSystem.scheduleDinoFeeding("VEL-02", "Blue", "Viande", 50, "normal");
203feedingSystem.scheduleDinoFeeding("TRCP-03", "Trixie", "Plantes", 120, "normal");
204feedingSystem.scheduleDinoFeeding("BRCH-04", "Bronty", "Plantes", 250, "normal");
205feedingSystem.scheduleDinoFeeding("STEG-05", "Spike", "Plantes", 100, "high");
206
207// 3. Rapport de l'état de l'inventaire avant le repas
208feedingSystem.reportInventoryStatus();
209
210// 4. Traitement du cycle de repas
211feedingSystem.processFeedingCycle(3); // Traite seulement 3 repas
212
213// 5. Vérification de l'état de l'inventaire après le repas
214feedingSystem.reportInventoryStatus();
215
216// 6. Terminer le cycle de repas
217feedingSystem.processFeedingCycle(5); // Traite les repas restants
218
219// 7. Vérification de l'état de l'inventaire après le cycle complet
220feedingSystem.reportInventoryStatus();Exemple 2 : Gestion des équipes du personnel du parc
1// Système de gestion des équipes du personnel de Jurassic Park
2const staffManagementSystem = {
3 // Données du système
4 departments: [
5 { id: "OPS", name: "Opérations" },
6 { id: "SCI", name: "Recherche scientifique" },
7 { id: "SEC", name: "Sécurité" },
8 { id: "VET", name: "Service vétérinaire" },
9 { id: "MAINT", name: "Maintenance" }
10 ],
11 staff: [],
12 teams: [],
13
14 // Ajout d'un nouvel employé
15 addStaffMember: function(name, role, skills, departmentId) {
16 // Vérifie si le département existe
17 const department = this.departments.find(dept => dept.id === departmentId);
18 if (!department) {
19 console.log(`Erreur : le département avec l'ID "${departmentId}" n'existe pas.`);
20 return null;
21 }
22
23 // Génère l'ID de l'employé
24 const id = `${departmentId}-${(this.staff.length + 1).toString().padStart(3, '0')}`;
25
26 const staffMember = {
27 id,
28 name,
29 role,
30 skills: Array.isArray(skills) ? skills : [skills],
31 departmentId,
32 departmentName: department.name,
33 hireDate: new Date().toISOString().split('T')[0]
34 };
35
36 this.staff.push(staffMember);
37 console.log(`Employé ajouté : ${name} (${role}) au département ${department.name}`);
38
39 return staffMember;
40 },
41
42 // Création d'une nouvelle équipe
43 createTeam: function(name, mission, leaderId) {
44 // Vérifie si le leader existe
45 const leader = this.staff.find(person => person.id === leaderId);
46 if (!leader) {
47 console.log(`Erreur : l'employé avec l'ID "${leaderId}" n'existe pas.`);
48 return null;
49 }
50
51 const teamId = `TEAM-${(this.teams.length + 1).toString().padStart(3, '0')}`;
52
53 const team = {
54 id: teamId,
55 name,
56 mission,
57 createdAt: new Date().toISOString().split('T')[0],
58 leaderId,
59 leaderName: leader.name,
60 members: [leaderId],
61 status: "active"
62 };
63
64 this.teams.push(team);
65 console.log(`Équipe créée : ${name} (mission : ${mission}), leader : ${leader.name}`);
66
67 return team;
68 },
69
70 // Ajout d'un employé à une équipe
71 addMemberToTeam: function(teamId, memberId) {
72 // Recherche l'équipe
73 const teamIndex = this.teams.findIndex(team => team.id === teamId);
74 if (teamIndex === -1) {
75 console.log(`Erreur : l'équipe avec l'ID "${teamId}" n'existe pas.`);
76 return false;
77 }
78
79 // Recherche l'employé
80 const member = this.staff.find(person => person.id === memberId);
81 if (!member) {
82 console.log(`Erreur : l'employé avec l'ID "${memberId}" n'existe pas.`);
83 return false;
84 }
85
86 // Vérifie si l'employé est déjà dans l'équipe
87 if (this.teams[teamIndex].members.includes(memberId)) {
88 console.log(`${member.name} fait déjà partie de l'équipe ${this.teams[teamIndex].name}.`);
89 return false;
90 }
91
92 // Ajoute l'employé à l'équipe
93 this.teams[teamIndex].members.push(memberId);
94 console.log(`Ajout de ${member.name} à l'équipe ${this.teams[teamIndex].name}.`);
95
96 return true;
97 },
98
99 // Suppression d'un employé d'une équipe
100 removeMemberFromTeam: function(teamId, memberId) {
101 // Recherche l'équipe
102 const teamIndex = this.teams.findIndex(team => team.id === teamId);
103 if (teamIndex === -1) {
104 console.log(`Erreur : l'équipe avec l'ID "${teamId}" n'existe pas.`);
105 return false;
106 }
107
108 // Vérifie si l'employé est le leader
109 if (this.teams[teamIndex].leaderId === memberId) {
110 console.log(`Erreur : impossible de retirer le leader de l'équipe. Change d'abord le leader.`);
111 return false;
112 }
113
114 // Recherche l'index de l'employé dans l'équipe
115 const memberIndex = this.teams[teamIndex].members.indexOf(memberId);
116 if (memberIndex === -1) {
117 console.log(`L'employé ne fait pas partie de l'équipe ${this.teams[teamIndex].name}.`);
118 return false;
119 }
120
121 // Recherche l'employé à titre informatif
122 const member = this.staff.find(person => person.id === memberId);
123
124 // Retire l'employé de l'équipe
125 this.teams[teamIndex].members.splice(memberIndex, 1);
126 console.log(`Retrait de ${member ? member.name : memberId} de l'équipe ${this.teams[teamIndex].name}.`);
127
128 return true;
129 },
130
131 // Changement du leader de l'équipe
132 changeTeamLeader: function(teamId, newLeaderId) {
133 // Recherche l'équipe
134 const teamIndex = this.teams.findIndex(team => team.id === teamId);
135 if (teamIndex === -1) {
136 console.log(`Erreur : l'équipe avec l'ID "${teamId}" n'existe pas.`);
137 return false;
138 }
139
140 // Vérifie si le nouveau leader existe
141 const newLeader = this.staff.find(person => person.id === newLeaderId);
142 if (!newLeader) {
143 console.log(`Erreur : l'employé avec l'ID "${newLeaderId}" n'existe pas.`);
144 return false;
145 }
146
147 // Vérifie si le nouveau leader est membre de l'équipe
148 if (!this.teams[teamIndex].members.includes(newLeaderId)) {
149 // Ajoute le nouveau leader à l'équipe s'il n'en est pas déjà membre
150 this.teams[teamIndex].members.push(newLeaderId);
151 console.log(`${newLeader.name} a été ajouté à l'équipe comme nouveau leader.`);
152 }
153
154 // Sauvegarde les infos de l'ancien leader pour le message
155 const oldLeaderId = this.teams[teamIndex].leaderId;
156 const oldLeader = this.staff.find(person => person.id === oldLeaderId);
157
158 // Met à jour le leader
159 this.teams[teamIndex].leaderId = newLeaderId;
160 this.teams[teamIndex].leaderName = newLeader.name;
161
162 console.log(`Le leader de l'équipe ${this.teams[teamIndex].name} passe de ${oldLeader.name} à ${newLeader.name}.`);
163 return true;
164 },
165
166 // Désactivation d'une équipe
167 deactivateTeam: function(teamId, reason) {
168 // Recherche l'équipe
169 const teamIndex = this.teams.findIndex(team => team.id === teamId);
170 if (teamIndex === -1) {
171 console.log(`Erreur : l'équipe avec l'ID "${teamId}" n'existe pas.`);
172 return false;
173 }
174
175 // Sauvegarde l'état avant modification
176 const teamName = this.teams[teamIndex].name;
177
178 // Met à jour le statut de l'équipe
179 this.teams[teamIndex].status = "inactive";
180 this.teams[teamIndex].deactivatedAt = new Date().toISOString().split('T')[0];
181 this.teams[teamIndex].deactivationReason = reason || "Non précisée";
182
183 console.log(`L'équipe ${teamName} a été désactivée. Raison : ${this.teams[teamIndex].deactivationReason}`);
184 return true;
185 },
186
187 // Génération d'un rapport des équipes
188 generateTeamsReport: function(includeInactive = false) {
189 console.log("=== RAPPORT DES ÉQUIPES DE JURASSIC PARK ===");
190
191 // Filtre les équipes par statut si les inactives ne sont pas incluses
192 const teamsToReport = includeInactive
193 ? this.teams
194 : this.teams.filter(team => team.status === "active");
195
196 if (teamsToReport.length === 0) {
197 console.log("Aucune équipe à afficher.");
198 return { teams: [] };
199 }
200
201 // Prépare les données du rapport
202 const teamsData = teamsToReport.map(team => {
203 // Récupère les informations complètes des membres
204 const memberDetails = team.members.map(memberId => {
205 const member = this.staff.find(person => person.id === memberId);
206 return member ? {
207 id: member.id,
208 name: member.name,
209 role: member.role,
210 isLeader: memberId === team.leaderId
211 } : { id: memberId, name: "Inconnu", role: "Inconnu", isLeader: false };
212 });
213
214 return {
215 id: team.id,
216 name: team.name,
217 mission: team.mission,
218 status: team.status,
219 memberCount: team.members.length,
220 leader: this.staff.find(person => person.id === team.leaderId),
221 members: memberDetails,
222 createdAt: team.createdAt,
223 deactivatedAt: team.deactivatedAt,
224 deactivationReason: team.deactivationReason
225 };
226 });
227
228 // Trie les équipes - actives d'abord, puis par date de création
229 teamsData.sort((a, b) => {
230 if (a.status !== b.status) {
231 return a.status === "active" ? -1 : 1;
232 }
233 return new Date(b.createdAt) - new Date(a.createdAt);
234 });
235
236 // Affiche le résumé
237 console.log(`Nombre d'équipes : ${teamsData.length}`);
238 console.log(`Équipes actives : ${teamsData.filter(t => t.status === "active").length}`);
239 if (includeInactive) {
240 console.log(`Équipes inactives : ${teamsData.filter(t => t.status === "inactive").length}`);
241 }
242
243 // Affiche les détails de chaque équipe
244 teamsData.forEach(team => {
245 console.log(`\n${team.id}: ${team.name} (Statut : ${team.status})`);
246 console.log(`Mission : ${team.mission}`);
247 console.log(`Leader : ${team.leader ? team.leader.name : 'Aucun'} (${team.leader ? team.leader.role : ''})`);
248 console.log(`Nombre de membres : ${team.memberCount}`);
249 console.log("Membres :");
250 team.members.forEach(member => {
251 console.log(` - ${member.name} (${member.role})${member.isLeader ? ' [LEADER]' : ''}`);
252 });
253
254 if (team.status === "inactive") {
255 console.log(`Date de désactivation : ${team.deactivatedAt}`);
256 console.log(`Raison : ${team.deactivationReason}`);
257 }
258 });
259
260 return { teams: teamsData };
261 },
262
263 // Réorganisation des équipes
264 reorganizeTeams: function(fromTeamId, toTeamId, memberIds, dissolveSourceTeam = false) {
265 // Vérifie si les équipes existent
266 const fromTeamIndex = this.teams.findIndex(team => team.id === fromTeamId);
267 const toTeamIndex = this.teams.findIndex(team => team.id === toTeamId);
268
269 if (fromTeamIndex === -1 || toTeamIndex === -1) {
270 console.log(`Erreur : l'une des équipes ou les deux n'existent pas.`);
271 return false;
272 }
273
274 // Vérifie si les équipes sont actives
275 if (this.teams[fromTeamIndex].status !== "active" || this.teams[toTeamIndex].status !== "active") {
276 console.log(`Erreur : les équipes doivent être actives pour être réorganisées.`);
277 return false;
278 }
279
280 // Si aucun membre spécifique n'est indiqué, transfère tout le monde (sauf le leader)
281 const membersToMove = memberIds ||
282 this.teams[fromTeamIndex].members.filter(id => id !== this.teams[fromTeamIndex].leaderId);
283
284 // Transfère les membres
285 for (const memberId of membersToMove) {
286 // Vérifie si l'employé fait partie de l'équipe source
287 if (!this.teams[fromTeamIndex].members.includes(memberId)) {
288 console.log(`Erreur : l'employé avec l'ID ${memberId} ne fait pas partie de l'équipe source.`);
289 continue;
290 }
291
292 // Vérifie si l'employé est le leader (si on ne veut pas tous les transférer)
293 if (memberIds && memberId === this.teams[fromTeamIndex].leaderId) {
294 console.log(`Impossible de transférer le leader de l'équipe. Change d'abord le leader.`);
295 continue;
296 }
297
298 // Vérifie si l'employé fait déjà partie de l'équipe cible
299 if (this.teams[toTeamIndex].members.includes(memberId)) {
300 console.log(`L'employé avec l'ID ${memberId} fait déjà partie de l'équipe cible.`);
301 continue;
302 }
303
304 // Retire de l'équipe d'origine
305 const fromIndex = this.teams[fromTeamIndex].members.indexOf(memberId);
306 this.teams[fromTeamIndex].members.splice(fromIndex, 1);
307
308 // Ajoute à la nouvelle équipe
309 this.teams[toTeamIndex].members.push(memberId);
310
311 // Recherche le nom de l'employé pour les journaux
312 const member = this.staff.find(person => person.id === memberId);
313 console.log(`Transfert de ${member ? member.name : memberId} de l'équipe ${this.teams[fromTeamIndex].name} vers ${this.teams[toTeamIndex].name}`);
314 }
315
316 // Si on choisit de dissoudre l'équipe source et qu'il ne reste plus de membres
317 if (dissolveSourceTeam || this.teams[fromTeamIndex].members.length === 0) {
318 this.deactivateTeam(fromTeamId, "Réorganisation - équipe transférée");
319 }
320
321 return true;
322 }
323};
324
325// Démonstration du système de gestion des équipes du personnel
326console.log("=== DÉMONSTRATION DU SYSTÈME DE GESTION DES ÉQUIPES DU PERSONNEL ===");
327
328// 1. Ajout des employés
329const owen = staffManagementSystem.addStaffMember("Owen Grady", "Dresseur de dinosaures", ["Comportement animal", "Dressage", "Premiers secours"], "OPS");
330const claire = staffManagementSystem.addStaffMember("Claire Dearing", "Directrice des opérations", ["Gestion", "Marketing", "Administration"], "OPS");
331const dr_wu = staffManagementSystem.addStaffMember("Dr. Henry Wu", "Généticien en chef", ["Génétique", "Bio-ingénierie", "Clonage"], "SCI");
332const barry = staffManagementSystem.addStaffMember("Barry", "Dresseur adjoint", ["Dressage", "Soins aux animaux"], "OPS");
333const lowery = staffManagementSystem.addStaffMember("Lowery Cruthers", "Technicien systèmes", ["Informatique", "Surveillance", "Communication"], "SEC");
334const vivian = staffManagementSystem.addStaffMember("Vivian Krill", "Coordinatrice de la sécurité", ["Sécurité", "Communication", "Gestion de crise"], "SEC");
335const muldoon = staffManagementSystem.addStaffMember("Robert Muldoon", "Spécialiste de la sécurité", ["Armes à feu", "Sécurité", "Pistage"], "SEC");
336const malcolm = staffManagementSystem.addStaffMember("Dr. Ian Malcolm", "Mathématicien", ["Théorie du chaos", "Analyse des risques", "Modélisation"], "SCI");
337const sattler = staffManagementSystem.addStaffMember("Dr. Ellie Sattler", "Paléobotaniste", ["Botanique", "Paléontologie", "Écologie"], "SCI");
338const harding = staffManagementSystem.addStaffMember("Dr. Gerry Harding", "Vétérinaire", ["Médecine vétérinaire", "Zoologie", "Médecine"], "VET");
339
340// 2. Création des équipes
341const raptorTeam = staffManagementSystem.createTeam("Équipe Velociraptor", "Dressage et soins des Velociraptors", owen.id);
342staffManagementSystem.addMemberToTeam(raptorTeam.id, barry.id);
343
344const securityTeam = staffManagementSystem.createTeam("Équipe de sécurité", "Assurer la sécurité du parc", muldoon.id);
345staffManagementSystem.addMemberToTeam(securityTeam.id, vivian.id);
346staffManagementSystem.addMemberToTeam(securityTeam.id, lowery.id);
347
348const scienceTeam = staffManagementSystem.createTeam("Équipe scientifique", "Recherche et développement scientifiques", dr_wu.id);
349staffManagementSystem.addMemberToTeam(scienceTeam.id, malcolm.id);
350staffManagementSystem.addMemberToTeam(scienceTeam.id, sattler.id);
351
352// 3. Rapport des équipes
353staffManagementSystem.generateTeamsReport();
354
355// 4. Réorganisation des équipes
356console.log("\n=== RÉORGANISATION DES ÉQUIPES ===");
357
358// Création d'une nouvelle équipe de gestion de crise
359const crisisTeam = staffManagementSystem.createTeam("Équipe de gestion de crise", "Réagir aux situations de crise", claire.id);
360
361// Transfert de membres depuis d'autres équipes
362staffManagementSystem.reorganizeTeams(securityTeam.id, crisisTeam.id, [vivian.id]);
363staffManagementSystem.addMemberToTeam(crisisTeam.id, malcolm.id); // Ajout de Malcolm comme conseiller en gestion des risques
364staffManagementSystem.addMemberToTeam(crisisTeam.id, harding.id); // Ajout du vétérinaire
365
366// Changement du leader de l'équipe scientifique
367staffManagementSystem.changeTeamLeader(scienceTeam.id, sattler.id);
368
369// Désactivation d'une équipe
370staffManagementSystem.deactivateTeam(raptorTeam.id, "Projet suspendu - incident avec les raptors");
371
372// 5. Rapport final des équipes (incluant les inactives)
373staffManagementSystem.generateTeamsReport(true);Récapitulatif
Dans cette leçon, nous avons appris les méthodes de base pour modifier les tableaux en JavaScript :
- push() - ajoute des éléments à la fin d'un tableau
- pop() - retire et renvoie le dernier élément d'un tableau
- unshift() - ajoute des éléments au début d'un tableau
- shift() - retire et renvoie le premier élément d'un tableau
- splice() - ajoute, retire ou remplace des éléments à n'importe quelle position d'un tableau
- sort() - trie les éléments d'un tableau
- reverse() - inverse l'ordre des éléments d'un tableau
- fill() - remplit les éléments d'un tableau avec une valeur spécifiée
La capacité à utiliser efficacement ces méthodes est cruciale pour travailler avec des données en JavaScript. Elles te permettent de gérer des collections, d'implémenter des structures de données (comme des piles et des files), et de manipuler les données efficacement.
Il est important de se rappeler que les méthodes ci-dessus modifient le tableau original (sauf si tu crées une copie avant de les appliquer). Dans une des prochaines leçons, nous apprendrons les méthodes de tableaux qui ne modifient pas l'original mais renvoient un nouveau tableau ou une nouvelle valeur.
Code de cette leçon : index.js
1// Méthodes des tableaux - Parc Jurassique
2console.log("Laboratoire des Méthodes de Tableaux");
3console.log("Opérations avancées sur les collections\n");
4
5// ===========================================
6// 1. forEach() - ITÉRATION
7// ===========================================
8console.log("=== 1. forEach() - Itération ===");
9
10const dinosaurs = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"];
11
12console.log("\nListe des dinosaures:");
13dinosaurs.forEach((dino, index) => {
14 console.log(` ${index + 1}. ${dino}`);
15});
16
17// forEach avec tous les paramètres
18console.log("\nVersion complète de forEach:");
19dinosaurs.forEach((element, index, array) => {
20 console.log(` [${index}] ${element} du tableau de longueur ${array.length}`);
21});
22
23// ===========================================
24// 2. map() - TRANSFORMATION
25// ===========================================
26console.log("\n=== 2. map() - Transformation ===");
27
28const dinoData = [
29 { name: "T-Rex", weight: 8000 },
30 { name: "Velociraptor", weight: 80 },
31 { name: "Triceratops", weight: 9000 }
32];
33
34// Extraction des noms seulement
35const names = dinoData.map(dino => dino.name);
36console.log("\nNoms seulement:", names);
37
38// Transformation vers un nouveau format
39const formatted = dinoData.map(dino => ({
40 species: dino.name,
41 weightInTons: dino.weight / 1000,
42 category: dino.weight > 1000 ? "Grand" : "Petit"
43}));
44
45console.log("\nTransformées:");
46formatted.forEach(d => {
47 console.log(` ${d.species}: ${d.weightInTons}t - ${d.category}`);
48});
49
50// ===========================================
51// 3. filter() - FILTRAGE
52// ===========================================
53console.log("\n=== 3. filter() - Filtrage ===");
54
55const allDinos = [
56 { name: "T-Rex", weight: 8000, carnivore: true },
57 { name: "Velociraptor", weight: 80, carnivore: true },
58 { name: "Triceratops", weight: 9000, carnivore: false },
59 { name: "Stegosaurus", weight: 5000, carnivore: false },
60 { name: "Brachiosaurus", weight: 50000, carnivore: false }
61];
62
63// Seulement les carnivores
64const carnivores = allDinos.filter(dino => dino.carnivore);
65console.log("\nCarnivores:", carnivores.map(d => d.name));
66
67// Dinosaures lourds (> 5000kg)
68const heavy = allDinos.filter(dino => dino.weight > 5000);
69console.log("Lourds (>5t):", heavy.map(d => d.name));
70
71// Combinaison de conditions
72const heavyCarnivores = allDinos.filter(d => d.carnivore && d.weight > 100);
73console.log("Carnivores lourds:", heavyCarnivores.map(d => d.name));
74
75// ===========================================
76// 4. find() et findIndex()
77// ===========================================
78console.log("\n=== 4. find() et findIndex() ===");
79
80const park = [
81 { id: 1, name: "T-Rex", sector: "A" },
82 { id: 2, name: "Velociraptor", sector: "B" },
83 { id: 3, name: "Triceratops", sector: "C" }
84];
85
86// find() - premier élément qui remplit une condition
87const foundDino = park.find(dino => dino.sector === "B");
88console.log("\nfind(sector === 'B'):", foundDino);
89
90// findIndex() - index du premier élément
91const foundIndex = park.findIndex(dino => dino.name === "Triceratops");
92console.log("findIndex(name === 'Triceratops'):", foundIndex);
93
94// Élément non trouvé
95const notFound = park.find(dino => dino.name === "Pteranodon");
96console.log("find(Pteranodon):", notFound); // undefined
97
98// ===========================================
99// 5. reduce() - AGRÉGATION
100// ===========================================
101console.log("\n=== 5. reduce() - Agrégation ===");
102
103const weights = [
104 { name: "T-Rex", weight: 8000 },
105 { name: "Velociraptor", weight: 80 },
106 { name: "Triceratops", weight: 9000 },
107 { name: "Stegosaurus", weight: 5000 }
108];
109
110// Somme des poids
111const totalWeight = weights.reduce((sum, dino) => sum + dino.weight, 0);
112console.log(`\nPoids total: ${totalWeight}kg`);
113
114// Poids moyen
115const avgWeight = totalWeight / weights.length;
116console.log(`Poids moyen: ${avgWeight.toFixed(2)}kg`);
117
118// Regroupement par poids
119const grouped = weights.reduce((acc, dino) => {
120 const category = dino.weight > 1000 ? "heavy" : "light";
121 if (!acc[category]) acc[category] = [];
122 acc[category].push(dino.name);
123 return acc;
124}, {});
125
126console.log("\nRegroupées:");
127console.log(" Lourds:", grouped.heavy);
128console.log(" Légers:", grouped.light);
129
130// Recherche du maximum
131const heaviest = weights.reduce((max, dino) =>
132 dino.weight > max.weight ? dino : max
133);
134console.log(`\nLe plus lourd: ${heaviest.name} (${heaviest.weight}kg)`);
135
136// ===========================================
137// 6. some() et every()
138// ===========================================
139console.log("\n=== 6. some() et every() ===");
140
141const herd = [
142 { name: "Trike", health: 95 },
143 { name: "Stego", health: 88 },
144 { name: "Brachio", health: 72 }
145];
146
147// some() - au moins un
148const hasSick = herd.some(dino => dino.health < 80);
149console.log("\nY a-t-il des malades (<80%):", hasSick);
150
151const hasHealthy = herd.some(dino => dino.health > 90);
152console.log("Y en a-t-il en très bonne santé (>90%):", hasHealthy);
153
154// every() - tous
155const allHealthy = herd.every(dino => dino.health >= 80);
156console.log("Tous en bonne santé (≥80%):", allHealthy);
157
158const allCritical = herd.every(dino => dino.health < 50);
159console.log("Tous critiques (<50%):", allCritical);
160
161// ===========================================
162// 7. sort() - TRI
163// ===========================================
164console.log("\n=== 7. sort() - Tri ===");
165
166const unsorted = ["Velociraptor", "T-Rex", "Brachiosaurus", "Stegosaurus"];
167
168// Alphabétiquement
169const alphabetical = [...unsorted].sort();
170console.log("\nAlphabétiquement:", alphabetical);
171
172// Ordre alphabétique inverse
173const reverseAlpha = [...unsorted].sort((a, b) => b.localeCompare(a));
174console.log("Inverse:", reverseAlpha);
175
176// Tri d'objets
177const dinoStats = [
178 { name: "T-Rex", health: 85 },
179 { name: "Velociraptor", health: 100 },
180 { name: "Triceratops", health: 70 }
181];
182
183const byHealth = [...dinoStats].sort((a, b) => b.health - a.health);
184console.log("\nPar santé (décroissant):");
185byHealth.forEach(d => console.log(` ${d.name}: ${d.health}%`));
186
187// ===========================================
188// 8. CHAÎNAGE DE MÉTHODES
189// ===========================================
190console.log("\n=== 8. Chaînage de méthodes ===");
191
192const inventory = [
193 { name: "Rexy", species: "T-Rex", sector: "A", health: 95, carnivore: true },
194 { name: "Blue", species: "Velociraptor", sector: "B", health: 100, carnivore: true },
195 { name: "Charlie", species: "Velociraptor", sector: "B", health: 85, carnivore: true },
196 { name: "Trike", species: "Triceratops", sector: "C", health: 70, carnivore: false },
197 { name: "Stego", species: "Stegosaurus", sector: "C", health: 92, carnivore: false }
198];
199
200// Trouver les carnivores en bonne santé et les trier par nom
201const healthyCarnivores = inventory
202 .filter(d => d.carnivore)
203 .filter(d => d.health >= 90)
204 .map(d => d.name)
205 .sort();
206
207console.log("\nCarnivores en bonne santé (≥90%):", healthyCarnivores);
208
209// Somme de santé des herbivores
210const herbivoreHealth = inventory
211 .filter(d => !d.carnivore)
212 .reduce((sum, d) => sum + d.health, 0);
213
214console.log(`Somme de santé des herbivores: ${herbivoreHealth}%`);
215
216// ===========================================
217// 9. flat() et flatMap()
218// ===========================================
219console.log("\n=== 9. flat() et flatMap() ===");
220
221const sectors = [
222 ["T-Rex", "Spinosaurus"],
223 ["Velociraptor", "Dilophosaurus"],
224 ["Triceratops", "Stegosaurus"]
225];
226
227// flat() - aplatissement d'un tableau imbriqué
228const flatDinos = sectors.flat();
229console.log("\nflat():", flatDinos);
230
231// flatMap() - map + flat en une seule opération
232const withEmoji = sectors.flatMap(sector =>
233 sector.map(dino => `${dino}`)
234);
235console.log("flatMap():", withEmoji);
236
237// ===========================================
238// 10. EXEMPLE COMPLET
239// ===========================================
240console.log("\n=== 10. Système d'analyse - exemple complet ===");
241
242class DinosaurAnalytics {
243 constructor(dinosaurs) {
244 this.dinosaurs = dinosaurs;
245 }
246
247 // Statistiques générales
248 getOverallStats() {
249 const total = this.dinosaurs.length;
250 const avgHealth = this.dinosaurs.reduce((sum, d) => sum + d.health, 0) / total;
251 const carnivoreCount = this.dinosaurs.filter(d => d.carnivore).length;
252
253 return {
254 total,
255 avgHealth: avgHealth.toFixed(1),
256 carnivores: carnivoreCount,
257 herbivores: total - carnivoreCount
258 };
259 }
260
261 // Top N par santé
262 getHealthiest(n = 3) {
263 return this.dinosaurs
264 .sort((a, b) => b.health - a.health)
265 .slice(0, n)
266 .map(d => ({ name: d.name, health: d.health }));
267 }
268
269 // Regroupement par secteur
270 groupBySector() {
271 return this.dinosaurs.reduce((acc, dino) => {
272 if (!acc[dino.sector]) acc[dino.sector] = [];
273 acc[dino.sector].push(dino.name);
274 return acc;
275 }, {});
276 }
277
278 // Alertes pour les malades
279 getHealthAlerts() {
280 return this.dinosaurs
281 .filter(d => d.health < 80)
282 .map(d => ({
283 name: d.name,
284 sector: d.sector,
285 health: d.health,
286 priority: d.health < 50 ? "CRITIQUE" : "ATTENTION"
287 }))
288 .sort((a, b) => a.health - b.health);
289 }
290
291 // Rapport du secteur
292 getSectorReport(sector) {
293 const dinosInSector = this.dinosaurs.filter(d => d.sector === sector);
294
295 if (dinosInSector.length === 0) {
296 return { error: `Aucun dinosaure dans le secteur ${sector}` };
297 }
298
299 const avgHealth = dinosInSector.reduce((sum, d) => sum + d.health, 0) / dinosInSector.length;
300 const carnivores = dinosInSector.filter(d => d.carnivore);
301 const herbivores = dinosInSector.filter(d => !d.carnivore);
302
303 return {
304 sector,
305 total: dinosInSector.length,
306 avgHealth: avgHealth.toFixed(1),
307 carnivores: carnivores.map(d => d.name),
308 herbivores: herbivores.map(d => d.name),
309 list: dinosInSector.map(d => `${d.name} (${d.health}%)`)
310 };
311 }
312
313 // Afficher toutes les analyses
314 displayFullReport() {
315 console.log("\nRAPPORT ANALYTIQUE COMPLET");
316 console.log("=".repeat(70));
317
318 // Statistiques générales
319 const stats = this.getOverallStats();
320 console.log("\nStatistiques générales:");
321 console.log(` Total des dinosaures: ${stats.total}`);
322 console.log(` Santé moyenne: ${stats.avgHealth}%`);
323 console.log(` Carnivores: ${stats.carnivores}`);
324 console.log(` Herbivores: ${stats.herbivores}`);
325
326 // Les plus en bonne santé
327 const healthiest = this.getHealthiest(3);
328 console.log("\nTOP 3 - Les plus en bonne santé:");
329 healthiest.forEach((d, i) => {
330 console.log(` ${i + 1}. ${d.name} - ${d.health}%`);
331 });
332
333 // Répartition par secteurs
334 const sectors = this.groupBySector();
335 console.log("\nRépartition par secteurs:");
336 Object.entries(sectors).sort().forEach(([sector, dinos]) => {
337 console.log(` Secteur ${sector}: ${dinos.join(", ")}`);
338 });
339
340 // Alertes de santé
341 const alerts = this.getHealthAlerts();
342 if (alerts.length > 0) {
343 console.log("\nALERTES DE SANTÉ:");
344 alerts.forEach(alert => {
345 console.log(` [${alert.priority}] ${alert.name} - Secteur ${alert.sector} - ${alert.health}%`);
346 });
347 } else {
348 console.log("\nAucune alerte de santé");
349 }
350
351 // Rapports des secteurs
352 const uniqueSectors = [...new Set(this.dinosaurs.map(d => d.sector))].sort();
353 console.log("\nDÉTAILS DES SECTEURS:");
354 uniqueSectors.forEach(sector => {
355 const report = this.getSectorReport(sector);
356 console.log(`\n Secteur ${report.sector}:`);
357 console.log(` Dinosaures: ${report.total}`);
358 console.log(` Santé moyenne: ${report.avgHealth}%`);
359 if (report.carnivores.length > 0) {
360 console.log(` Carnivores: ${report.carnivores.join(", ")}`);
361 }
362 if (report.herbivores.length > 0) {
363 console.log(` Herbivores: ${report.herbivores.join(", ")}`);
364 }
365 });
366 }
367}
368
369// Données de test
370const testData = [
371 { name: "Rexy", species: "T-Rex", sector: "A", health: 95, carnivore: true },
372 { name: "Blue", species: "Velociraptor", sector: "B", health: 100, carnivore: true },
373 { name: "Charlie", species: "Velociraptor", sector: "B", health: 85, carnivore: true },
374 { name: "Delta", species: "Velociraptor", sector: "B", health: 45, carnivore: true },
375 { name: "Trike", species: "Triceratops", sector: "C", health: 70, carnivore: false },
376 { name: "Stego", species: "Stegosaurus", sector: "C", health: 92, carnivore: false },
377 { name: "Brachio", species: "Brachiosaurus", sector: "D", health: 88, carnivore: false }
378];
379
380// Exécuter l'analyse
381const analytics = new DinosaurAnalytics(testData);
382analytics.displayFullReport();
383
384console.log("\nFélicitations ! Tu maîtrises maintenant les méthodes des tableaux !");Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Que fait la méthode Array.prototype.pop() ?
2. Que va retourner typeof undefined ?
3. Quel est le moyen le plus simple de vérifier la valeur d'une variable pendant le débogage ?
4. Pourquoi utiliser const plutôt que let lorsque la valeur d'une variable ne changera pas ?
Tâches pratiques dans le jeu
- Éditeur de code
Crée un tableau species avec les espèces 'T-Rex', 'Velociraptor' et 'Triceratops'. Ajoute 'Stegosaurus' à la fin avec push(), supprime le premier élément avec shift() et enregistre-le dans une constante removed. Affiche dans la console le tableau species et sa longueur (length).
- Clique dans l'ordre
Range les éléments d'un littéral de template avec interpolation :
- Éditeur de code
Enregistre sous forme de BigInt : const dinoEraStart = 245000000n (le début de l'ère des dinosaures, en années avant aujourd'hui) et const dinoEraEnd = 66000000n (sa fin). Calcule dinoEraDuration comme la différence dinoEraStart - dinoEraEnd, et dinoEraDays comme dinoEraDuration multiplié par 365n. Affiche les deux résultats dans la console.
- Tri horizontal
Range les éléments permettant de vérifier le type d'une variable :
- Éditeur de code
Crée une constante species contenant le nom d'une espèce de dinosaure sous forme de texte, par exemple 'Tyrannosaurus Rex', et une variable age (let) avec l'âge 25. Après l'anniversaire, change age en 26 et affiche species et age dans la console.
- Tri vertical
Range les endroits où JavaScript recherche une variable (chaîne de portée) :
- Tri horizontal
Range les éléments d'une déclaration de fonction fléchée :
- Éditeur de code
Écris une fonction ageInMillions(years) qui renvoie l'âge d'un fossile en millions d'années, arrondi à un nombre entier avec Math.round(). Appelle-la pour un fossile vieux de 66000000 ans et affiche le résultat dans la console.
- Clique dans l'ordre
Range les étapes du processus d'allocation de mémoire pour les variables :
- Tri vertical
Range les étapes de vérification du type d'une variable dans du code de production :
- Tri vertical
Range l'introduction des nouveaux types de données JavaScript par ordre chronologique :
- Clique dans l'ordre
Range les éléments d'une déclaration de tableau en JavaScript
- Tri vertical
Range les étapes de gestion de la mémoire pour les variables en JavaScript :
- Tri horizontal
Range les éléments permettant d'ajouter un élément à un tableau :