Tableau en double : pourquoi cette tâche a rassemblé des milliers de vues sur Stack Overflow
\n\nImaginez : vous écrivez une boutique en ligne, l'utilisateur ajoute des produits au panier. Mais par erreur ou à cause d'un bug, le même iPhone apparaît trois fois dans la liste. Ou vous analysez une liste de balises depuis une base de données, et "JavaScript" apparaît 15 fois de suite. Que faire ? C'est simple — ne garder que les valeurs uniques.
\n\nLa question "Get all unique values in a JavaScript array (remove duplicates)" sur Stack Overflow a rassemblé des centaines de milliers de vues. Et ce n'est pas un hasard. La tâche semble simple, mais sous le capot se cache tout un arsenal d'approches : des solutions en une ligne en ES6 moderne aux astuces astucieuses avec filter et indexOf. Dans cet article, nous ne donnons pas seulement des solutions toutes faites, mais nous analysons comment chacune fonctionne au niveau du moteur JavaScript.
Prêts à jeter un œil sous le capot ? C'est parti !
\n\n\n\n
Méthode n°1 : Set — le roi de la performance
\n\nLa manière la plus élégante et la plus rapide d'obtenir des valeurs uniques dans un tableau JavaScript est d'utiliser l'objet Set. Il est apparu avec ES6 et a été littéralement créé pour cette tâche.
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = [...new Set(numbers)];\n\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]\n\nComment cela fonctionne-t-il sous le capot ?
\nL'objet Set ne stocke que des valeurs uniques. Lorsque nous passons un tableau au constructeur new Set(numbers), le moteur JavaScript parcourt chaque élément et l'ajoute dans une table de hachage interne. Si la valeur existe déjà, elle est ignorée. Ensuite, l'opérateur de décomposition ... reconvertit le Set en tableau.
Pourquoi est-ce rapide ? Parce que la recherche et l'insertion dans un Set s'effectuent en O(1) (temps constant). Pour un tableau de 10 000 éléments, la différence avec d'autres méthodes sera colossale.
\n\nImportant : Set conserve l'ordre des éléments, mais ne fonctionne qu'avec des primitives (nombres, chaînes de caractères, booléens). Pour les objets, la comparaison se fait par référence, et non par contenu.
\n\nQuand l'utiliser ?
\n- \n
- Si le tableau est composé de nombres ou de chaînes de caractères. \n
- Si la vitesse de traitement de grands tableaux est importante. \n
- Si vous écrivez du code moderne et n'avez pas peur d'ES6. \n
\n\n
Méthode n°2 : filter + indexOf — un classique du genre
\n\nCette méthode est un vétéran de JavaScript. Elle fonctionne dans tous les navigateurs sans polyfill et reste populaire sur Stack Overflow.
\n\nconst numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.filter((value, index, arr) => {\n return arr.indexOf(value) === index;\n});\n\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]\n\nAnalyse de la logique
\nLa méthode filter crée un nouveau tableau, en ne conservant que les éléments pour lesquels le callback retourne true. À l'intérieur du callback, nous vérifions : l'index actuel est-il la première occurrence de cette valeur dans le tableau ? Si oui, nous conservons l'élément. Si la valeur est déjà apparue auparavant, indexOf retournera un index plus petit, la condition ne sera pas remplie, et le doublon sera rejeté.
Piège : indexOf parcourt le tableau depuis le début à chaque fois. Cela donne une complexité de O(n²). Pour les petits tableaux (jusqu'à 1000 éléments), la différence est imperceptible, mais sur 100 000 éléments, le navigateur peut se bloquer pendant une seconde.
Quand l'utiliser ?
\n- \n
- Si vous devez prendre en charge les anciens navigateurs (IE11). \n
- Si le tableau est petit. \n
- Si vous voulez montrer clairement la logique de la "première occurrence". \n
\n\n
Méthode n°3 : reduce + accumulateur — flexibilité et contrôle
\n\nLa méthode reduce offre un contrôle total sur le processus. Nous décidons nous-mêmes comment collecter le résultat.
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.reduce((acc, value) => {\n if (!acc.includes(value)) {\n acc.push