Introduction aux Set en JavaScript
Les Set en JavaScript sont des collections d'éléments uniques introduites dans ES6. Contrairement aux tableaux, les Set garantissent l'unicité des valeurs et préservent l'ordre d'insertion. Cependant, comme les Map, les Set ne disposent pas d'une méthode sort() intégrée. Dans ce guide complet, nous allons explorer différentes techniques pour trier un Set en JavaScript, que ce soit des nombres, des chaînes de caractères, ou des objets complexes.
Méthode 1 : Convertir en tableau, trier, puis recréer un Set
La méthode la plus courante pour trier un Set consiste à le convertir en tableau, le trier, puis créer un nouveau Set à partir du tableau trié. Cette approche est simple et efficace.
const monSet = new Set([3, 1, 4, 1, 5, 9, 2, 6]);
console.log(monSet);
const setTrie = new Set([...monSet].sort((a, b) => a - b));
console.log(setTrie);
const setTrieDesc = new Set([...monSet].sort((a, b) => b - a));
console.log(setTrieDesc);
Explication
L'opérateur de décomposition [...monSet] convertit le Set en tableau. Nous utilisons ensuite la méthode sort() avec une fonction de comparaison pour trier les éléments, puis nous créons un nouveau Set à partir du tableau trié. Notez que les valeurs dupliquées sont automatiquement supprimées lors de la création du Set initial.
Trier un Set de chaînes de caractères
Pour trier un Set contenant des chaînes de caractères, nous utilisons localeCompare() pour un tri alphabétique correct qui prend en compte les accents et les caractères spéciaux.
const fruits = new Set(['pomme', 'banane', 'cerise', 'datte', 'ananas']);
const fruitsTries = new Set([...fruits].sort((a, b) => a.localeCompare(b)));
console.log(fruitsTries);
const fruitsTriesDesc = new Set([...fruits].sort((a, b) => b.localeCompare(a)));
console.log(fruitsTriesDesc);
Trier un Set d'objets
Lorsque vous travaillez avec un Set d'objets, vous devez spécifier la propriété par laquelle vous souhaitez trier. Voici comment procéder :
const personnes = new Set([
{ nom: 'Alice', age: 30 },
{ nom: 'Bob', age: 25 },
{ nom: 'Charlie', age: 35 },
{ nom: 'Diana', age: 28 }
]);
const personnesTrieesParAge = new Set(
[...personnes].sort((a, b) => a.age - b.age)
);
console.log(personnesTrieesParAge);
const personnesTrieesParNom = new Set(
[...personnes].sort((a, b) => a.nom.localeCompare(b.nom))
);
console.log(personnesTrieesParNom);
Créer une fonction réutilisable
Pour une meilleure organisation du code, vous pouvez créer une fonction utilitaire générique qui fonctionne avec différents types de données :
function trierSet(set, comparateur) {
return new Set([...set].sort(comparateur));
}
const nombres = new Set([3, 1, 4, 1, 5, 9, 2, 6]);
const nombresTries = trierSet(nombres, (a, b) => a - b);
const mots = new Set(['zèbre', 'abeille', 'chat', 'chien']);
const motsTries = trierSet(mots, (a, b) => a.localeCompare(b));
const produits = new Set([
{ nom: 'Laptop', prix: 999 },
{ nom: 'Souris', prix: 25 },
{ nom: 'Clavier', prix: 75 }
]);
const produitsTries = trierSet(produits, (a, b) => a.prix - b.prix);
Fonction avancée avec options
Voici une version plus avancée qui gère automatiquement les différents types de données :
function trierSetAvance(set, options = {}) {
const {
cle = null,
ordre = 'croissant'
} = options;
const comparer = (a, b) => {
const aVal = cle ? a[cle] : a;
const bVal = cle ? b[cle] : b;
if (typeof aVal === 'number' && typeof bVal === 'number') {
return ordre === 'croissant' ? aVal - bVal : bVal - aVal;
}
if (typeof aVal === 'string' && typeof bVal === 'string') {
const resultat = aVal.localeCompare(bVal);
return ordre === 'croissant' ? resultat : -resultat;
}
if (ordre === 'croissant') {
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
} else {
return aVal > bVal ? -1 : aVal < bVal ? 1 : 0;
}
};
return new Set([...set].sort(comparer));
}
const personnes = new Set([
{ nom: 'Alice', age: 30 },
{ nom: 'Bob', age: 25 }
]);
const parAge = trierSetAvance(personnes, { cle: 'age', ordre: 'croissant' });
const parNom = trierSetAvance(personnes, { cle: 'nom', ordre: 'decroissant' });
Cas d'usage pratiques
Scénario 1 : Trier des IDs uniques
const userIds = new Set([42, 15, 7, 23, 99, 1]);
const userIdsTries = new Set([...userIds].sort((a, b) => a - b));
console.log(userIdsTries);
const tags = new Set(['javascript', 'react', 'nodejs', 'typescript', 'vue']);
const tagsTries = new Set([...tags].sort((a, b) => a.localeCompare(b)));
console.log(tagsTries);
Scénario 3 : Trier des produits par prix
const produits = new Set([
{ id: 1, nom: 'Laptop', prix: 999 },
{ id: 2, nom: 'Souris', prix: 25 },
{ id: 3, nom: 'Clavier', prix: 75 },
{ id: 4, nom: 'Écran', prix: 200 }
]);
const produitsTries = new Set(
[...produits].sort((a, b) => a.prix - b.prix)
);
produitsTries.forEach(produit => {
console.log(`${produit.nom}: ${produit.prix}€`);
});
Le tri d'un Set a une complexité temporelle de O(n log n) due à l'algorithme de tri. Voici quelques points à considérer :
Les Set préservent l'unicité : même si vous triez, les doublons ne réapparaîtront pas
La conversion en tableau et la création d'un nouveau Set ont un coût en mémoire
Pour de très grandes collections, considérez l'utilisation d'un tableau trié ou d'une structure de données spécialisée
Si vous devez trier fréquemment, envisagez de maintenir un tableau trié parallèle plutôt que de trier à chaque fois
Comparaison avec les tableaux
Il est important de comprendre les différences entre Set et Array pour choisir la bonne structure de données :
Set : Garantit l'unicité, pas de méthode sort() intégrée, meilleur pour vérifier l'existence d'un élément
Array : Permet les doublons, méthode sort() intégrée, meilleur pour les opérations de tri fréquentes
Astuce : Si vous avez besoin à la fois d'unicité et de tri fréquent, considérez d'utiliser un tableau avec une vérification d'unicité lors de l'ajout, ou maintenez un Set pour l'unicité et un tableau trié pour l'affichage.
Conclusion
Nous avons couvert les aspects essentiels du tri de Set en JavaScript. Bien que les Set n'aient pas de méthode sort() intégrée, il est facile de les trier en les convertissant en tableaux. La méthode la plus courante consiste à utiliser l'opérateur de décomposition [...set], trier le tableau, puis créer un nouveau Set. Cette approche fonctionne efficacement pour les nombres, les chaînes de caractères, et même les objets complexes.
N'oubliez pas que les Set sont optimisés pour garantir l'unicité et vérifier l'existence d'éléments. Si le tri est une opération très fréquente dans votre cas d'usage, évaluez si un tableau ne serait pas plus approprié. La pratique et l'expérimentation vous aideront à choisir la meilleure structure de données pour vos besoins spécifiques.