Apprenez en lisant dans l'ordre

Trier et chercher — sort / find / some / every

sort trie un tableau selon une fonction de comparaison, toSorted garde l'original, find et findIndex renvoient un seul résultat. Avec some et every.

Si tu tries une liste avec une boucle for qui échange des éléments, tu dois gérer toi-même les comparaisons et les échanges, à chaque fois. Chercher le seul élément qui remplit une condition mène au même genre de code : une boucle for avec un break pour sortir dès que l'élément est trouvé.

Cet article présente sort, qui réordonne un tableau, et find, qui cherche un élément qui remplit une condition.

Indiquer l'ordre avec une fonction — sort et la fonction de comparaison

Imagine que tu veux afficher une liste de produits du moins cher au plus cher. Une méthode de tableau s'occupe du tri, mais écrire simplement products.sort() ne trie pas par prix, parce que tu ne lui as pas dit quoi comparer.

Tu passes à sort (une méthode qui réordonne les éléments d'un tableau) une fonction de comparaison (une fonction qui reçoit deux éléments et renvoie un nombre). Si on appelle a et b les deux éléments reçus, une valeur de retour négative place a en premier, et une valeur positive place b en premier. Si tu renvoies a.price - b.price, tu obtiens les prix par ordre croissant.

const products = [
  { name: "Souris sans fil", price: 2980 },
  { name: "Batterie externe", price: 4380 },
  { name: "Câble USB-C", price: 980 },
  { name: "Tapis de souris", price: 2980 },
];

// Si la soustraction est négative, a passe devant ; si elle est positive, b passe devant
products.sort((a, b) => a.price - b.price);
console.log(products.map((item) => item.price).join(", "));  // 980, 2980, 2980, 4380

// Vérifie l'ordre des deux produits au même prix
console.log(products[1].name, products[2].name);             // Souris sans fil Tapis de souris

// Inverse la soustraction et tu obtiens l'ordre décroissant
products.sort((a, b) => b.price - a.price);
console.log(products[0].name);                               // Batterie externe
Le nombre renvoyé par la fonction de comparaison décide de l'ordre
Comparaison :a.price - b.pricea vaut 980b vaut 2980a vaut 2980b vaut 2980a vaut 4380b vaut 980-2000renvoie un négatif0aucun écart3400renvoie un positifPlace a devantGarde l'ordred'originePlace b devant
La même fonction de comparaison renvoie un nombre différent selon les prix des deux produits qu'elle reçoit. Deux produits dont l'écart vaut 0 gardent l'ordre qu'ils avaient avant le tri.

sort ne regarde que le signe du nombre renvoyé : -2000 et -1 sont donc traités de la même façon. Si tu veux aussi contrôler l'ordre des produits au même prix, fais comparer une autre valeur à la fonction de comparaison quand l'écart vaut 0.

Tu mets les annonces d'une appli de vente entre particuliers dans l'ordre où elles apparaîtront à l'écran. listings est déjà déclaré.

① Trie selon le nombre de caractères du nom du produit, du plus court au plus long, et affiche les noms séparés par « , ».

② Trie par prix, du moins cher au plus cher, et affiche les noms de la même façon.

③ Trie de nouveau par prix, mais cette fois classe les annonces au même prix par nombre de likes, du plus grand au plus petit, et affiche les noms de la même façon.

(Si tout s'exécute correctement, une explication apparaîtra.)

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Appeler sort sans argument — comparaison par défaut et toSorted

Imagine que tu veux trier un tableau de durées de consultation d'une page, en secondes, du plus court au plus long. Si tu appelles sort() sans fonction de comparaison, le résultat ne suit pas l'ordre numérique : 1180 secondes passe avant 25 secondes.

Sans fonction de comparaison, sort convertit d'abord les éléments en chaînes, puis les compare caractère par caractère. 1180 est traité comme "1180" et 25 comme "25" : l'ordre se décide donc sur le premier caractère, 1 contre 2. sort réordonne sur place le tableau sur lequel il est appelé ; si tu veux aussi garder l'ordre d'origine, utilise toSorted (une méthode qui renvoie un nouveau tableau trié).

const viewSeconds = [1180, 980, 25, 4380];

// Sans fonction de comparaison, les valeurs sont comparées comme des chaînes
console.log(viewSeconds.sort().join(", "));                 // 1180, 25, 4380, 980

// Avec une fonction de comparaison, le tri suit l'ordre numérique
console.log(viewSeconds.sort((a, b) => a - b).join(", "));  // 25, 980, 1180, 4380

// toSorted renvoie un nouveau tableau et laisse l'original intact
const stayTimes = [1180, 980, 25, 4380];
console.log(stayTimes.toSorted((a, b) => a - b).join(", "));  // 25, 980, 1180, 4380
console.log(stayTimes.join(", "));                            // 1180, 980, 25, 4380
La fonction de comparaison change ce qui est comparé
Tu écrissort()Nombres convertisen chaînesCompare depuisle 1er caractère1180 restedevantTu passes(a, b) => a - bLes soustraitcomme nombres1180 - 25 estpositif25 passedevant
Les mêmes 1180 et 25 sont comparés comme des valeurs de nature différente selon que tu passes une fonction de comparaison ou non. Les deux lignes ne placent pas le même élément en premier.

Une fois converti en chaîne, "1180" passera toujours avant "25" : passe donc une fonction de comparaison quand tu tries un tableau de nombres. Le deuxième sort du code ci-dessus trie de nouveau viewSeconds, que le premier appel a déjà réordonné.

Ce que sort et toSorted font au tableau
viewSeconds.sort(...)Réécrit lemême tableauRenvoie cemême tableauL'ordre d'origineest perdustayTimes.toSorted(...)Lit seulement letableau d'origineRenvoie unnouveau tableauL'ordre d'origineest conservé
Ce que renvoie sort sur la ligne du haut, c'est viewSeconds lui-même, réordonné. Seul toSorted crée un nouveau tableau.

Les anciens navigateurs n'ont pas toSorted

toSorted a été ajouté à la spécification dans ES2023 : dans les anciens navigateurs qui ne le prennent pas en charge, la ligne qui l'appelle lève une TypeError. Pour que ton code marche aussi dans ces environnements, appelle sort sur une copie faite avec la syntaxe de décomposition, comme dans [...stayTimes].sort((a, b) => a - b).

Trie une liste d'identifiants de membres et une liste de quantités en stock, puis affiche les résultats. memberIds et stockCounts sont déjà déclarés.

① Trie memberIds sans passer de fonction de comparaison, et affiche-le en séparant les valeurs par « , ».

② Crée un nouveau tableau trié à partir de stockCounts, sans passer de fonction de comparaison, et affiche-le de la même façon.

③ Crée un nouveau tableau à partir de stockCounts, trié de la plus petite à la plus grande valeur, et affiche-le de la même façon.

④ Affiche le premier élément de stockCounts.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Récupérer le seul élément qui correspond — find et findIndex

Imagine que tu veux récupérer une réservation à partir de son code. Tu pourrais utiliser filter, mais il renvoie un tableau : tu devrais ajouter [0] pour lire le premier élément, et si aucune réservation ne correspond, tu récupères un tableau vide.

find (une méthode qui renvoie le premier élément qui remplit une condition) renvoie l'élément lui-même : le premier pour lequel le callback renvoie true. Si tu veux plutôt sa position, utilise findIndex (une méthode qui renvoie la position du premier élément qui remplit une condition).

const reservations = [
  { code: "RSV-201", room: "Salle de réunion A" },
  { code: "RSV-202", room: "Salle de réunion B" },
  { code: "RSV-203", room: "Salle de réunion C" },
];

// Renvoie le premier élément pour lequel le callback a renvoyé true
const target = reservations.find((item) => item.code === "RSV-202");
console.log(target.room);  // Salle de réunion B

// Utilise findIndex quand tu veux la position
console.log(reservations.findIndex((item) => item.code === "RSV-202"));  // 1

// Quand aucune réservation ne correspond
console.log(reservations.find((item) => item.code === "RSV-999"));       // undefined
console.log(reservations.findIndex((item) => item.code === "RSV-999"));  // -1
Les appels s'arrêtent dès qu'un élément correspond
1er : RSV-201renvoie falsePasse ausuivant2e : RSV-202renvoie truefind renvoiecet élément3e : RSV-203jamais vérifiéLa vérifications'arrête après 2
Une fois que le callback a renvoyé true pour le 2e élément, il n'est jamais appelé pour le 3e. Plus la correspondance arrive tôt, moins il y a d'appels.

find ne renvoie que le premier élément qui correspond : il ne peut donc pas rassembler toutes les correspondances quand il y en a plusieurs. Utilise filter, qui renvoie un tableau, quand tu as besoin de toutes, et find quand une seule suffit.

Tu obtiens undefined quand rien n'est trouvé

Si tu lis directement la valeur renvoyée par find, comme dans target.room, tu obtiens TypeError: Cannot read properties of undefined (reading 'room') quand aucun élément ne correspond. Vérifie-la avec if (target) avant de la lire.

Cherche des coupons selon différentes conditions. coupons est déjà déclaré, et un coupon dont la propriété expired vaut true est expiré.

① Affiche le taux de remise du coupon dont le code est MEMBRE15.

② Affiche la position (comptée à partir de 0) du coupon expiré.

③ Affiche le code du premier coupon non expiré.

④ Cherche le coupon dont le code est AUTOMNE30, et affiche son taux de remise s'il existe, ou « Introuvable » sinon.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Vérifier tout le tableau par vrai ou faux — some et every

Imagine que tu veux décider, d'après les stocks, si tous les articles d'une commande peuvent partir ensemble. Tu pourrais rassembler les articles en rupture avec filter et les compter, mais ce que tu veux, ce n'est pas un tableau : c'est une seule réponse, true ou false.

some (une méthode qui renvoie true si au moins un élément remplit la condition) et every (une méthode qui renvoie true si tous les éléments remplissent la condition) renvoient un booléen, pas un élément. Tu peux t'en servir directement comme condition d'un if.

const orderItems = [
  { name: "Flacon de recharge", stock: 12 },
  { name: "Savon pour les mains", stock: 0 },
  { name: "Filet moussant", stock: 5 },
];

// true si au moins un élément correspond
console.log(orderItems.some((item) => item.stock === 0));   // true

// true seulement si tous correspondent
console.log(orderItems.every((item) => item.stock > 0));    // false

// Sur un tableau vide, some vaut false et every vaut true
console.log([].some((item) => item.stock > 0));             // false
console.log([].every((item) => item.stock > 0));            // true
Où some et every arrêtent de vérifier
Appel de some :cherche stock 01er : 12renvoie false2e : 0renvoie trueRenvoie true,saute la suiteAppel de every :tout en stock ?1er : 12renvoie true2e : 0renvoie falseRenvoie false,saute la suite
some comme every ont leur réponse dès le 2e article, dont le stock vaut 0. every s'arrête dès qu'il trouve un élément qui ne correspond pas.

Sur un tableau vide, aucun élément ne remplit la condition, donc some vaut false ; et aucun élément ne l'enfreint non plus, donc every vaut true. Le tableau ci-dessous résume ce que renvoient les 4 méthodes de recherche vues dans cet article.

MéthodeRenvoieSi aucun ne correspond
findLe premier élément qui correspondundefined
findIndexL'index du premier qui correspond-1
sometrue si au moins un correspondfalse
everytrue si tous correspondentfalse (true pour un tableau vide)

Vérifie si chaque participant d'un cours en ligne peut obtenir une attestation de réussite, d'après le nombre de devoirs rendus et le taux de présence. learners est déjà déclaré.

① Affiche si tous les participants ont rendu au moins un devoir.

② Affiche si au moins un participant n'a rendu aucun devoir.

③ Affiche le nom du participant qui n'a rendu aucun devoir.

④ Affiche si tous les participants ont un taux de présence d'au moins 80 %.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Quand la fonction de comparaison renvoie une valeur négative, quel élément sort place-t-il en premier ?

Question 2Si tu appelles sort() sur [1180, 980, 25] sans fonction de comparaison, quel ordre obtiens-tu ?

Question 3Quelle méthode utilises-tu pour vérifier, avec un seul booléen, que toutes les quantités en stock valent 1 ou plus ?