2885 votes

Récupérer toutes les valeurs uniques dans un tableau JavaScript (supprimer les doublons)

J'ai un tableau de nombres dont je dois m'assurer qu'ils sont uniques. J'ai trouvé le code ci-dessous sur Internet et il fonctionne très bien jusqu'à ce que le tableau contienne un zéro. J'ai trouvé cet autre script ici sur Stack Overflow qui ressemble presque exactement à celui-ci, mais il n'échoue pas.

Donc, pour m'aider à apprendre, quelqu'un peut-il m'aider à déterminer où le prototype script fait fausse route ?

Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

Plus de réponses à partir de la question en double :

Question similaire :

6 votes

@hippietrail Cette ancienne question concerne la recherche et le retour des seuls doublons (j'étais aussi confus !). Ma question est plutôt de savoir pourquoi cette fonction échoue lorsqu'un tableau contient un zéro.

0 votes

Vous voudrez probablement aussi rendre le titre de votre question moins vague.

0 votes

Pour les futurs lecteurs, lorsque vous commencez à constater que vous devez modifier algorithmiquement le contenu de votre structure de données en permanence (les ordonner, supprimer les éléments répétitifs, etc.) ou rechercher des éléments à l'intérieur de celle-ci à chaque itération, il est prudent de supposer que vous utilisez la mauvaise structure de données en premier lieu et d'en utiliser une qui est plus appropriée pour la tâche à accomplir (dans ce cas, un ensemble de hachage au lieu d'un tableau).

4671voto

TLindig Points 2016

Avec JavaScript 1.6 / ECMAScript 5 vous pouvez utiliser la fonction native filter d'un tableau de la manière suivante pour obtenir un tableau avec des valeurs uniques :

function onlyUnique(value, index, self) {
  return self.indexOf(value) === index;
}

// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter(onlyUnique);

console.log(unique); // ['a', 1, 2, '1']

La méthode native filter bouclera le tableau et ne laissera que les entrées qui passent la fonction de rappel donnée. onlyUnique .

onlyUnique vérifie si la valeur donnée est la première à apparaître. Si ce n'est pas le cas, il doit s'agir d'un doublon et ne sera pas copié.

Cette solution fonctionne sans aucune bibliothèque supplémentaire comme jQuery ou prototype.js.

Cela fonctionne également pour les tableaux avec des types de valeurs mixtes.

Pour les anciens navigateurs (<ie9), qui ne supportent pas les méthodes natives filter y indexOf vous pouvez trouver des solutions de contournement dans la documentation MDN de l'outil filtre y indexOf .

Si vous voulez conserver la dernière occurrence d'une valeur, il suffit de remplacer indexOf con lastIndexOf .

Avec ES6, cela peut être raccourci :

// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);

console.log(unique); // unique is ['a', 1, 2, '1']

Merci à Camilo Martin pour l'indice dans le commentaire.

ES6 possède un objet natif Set pour stocker des valeurs uniques. Pour obtenir un tableau avec des valeurs uniques, vous pouvez maintenant faire ceci :

var myArray = ['a', 1, 'a', 2, '1'];

let unique = [...new Set(myArray)];

console.log(unique); // unique is ['a', 1, 2, '1']

Le constructeur de Set prend un objet itérable, comme un tableau, et l'opérateur d'étalement. ... transformer l'ensemble en un Array. Grâce à Lukas Liese pour l'indice dans le commentaire.

117 votes

Cette solution fonctionnera beaucoup plus lentement, malheureusement. Vous bouclez deux fois, une fois avec le filtre et une fois avec l'index de

54 votes

Dans le JS moderne : .filter((v,i,a)=>a.indexOf(v)==i) (notation en forme de flèche).

408 votes

let unique_values = [...new Set(random_array)]; developer.mozilla.org/fr/US/docs/Web/JavaScript/Référence/

233voto

Rafael Points 9065

Il n'est pas nécessaire d'utiliser 2 for des boucles, mettez juste un petit if déclaration dans une boucle

Array.prototype.getUnique = function(){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
}

165voto

kornfridge Points 1123

Vous pouvez également utiliser underscore.js .

console.log(_.uniq([1, 2, 1, 3, 1, 4]));

<script src="http://underscorejs.org/underscore-min.js"></script>

qui reviendra :

[1, 2, 3, 4]

29 votes

Faites-le, s'il vous plaît. N'ajoutez pas quelque chose au prototype Array. S'il vous plaît.

5 votes

@JacobDalton - Ce n'est pas une extension du prototype Array. C'est un espace de nom dans l'objet _.

28 votes

Je sais, c'est pourquoi j'ai dit "s'il vous plaît". faire ceci. La solution acceptée suggère de modifier le prototype Array. Ne faites pas cela.

53voto

Mottie Points 31167

J'ai depuis trouvé une méthode agréable qui utilise jQuery

arr = $.grep(arr, function(v, k){
    return $.inArray(v ,arr) === k;
});

Note : Ce code a été tiré de Le poste de frappe du canard de Paul Irish - J'ai oublié de donner le crédit :P

12 votes

Une solution concise, mais l'appel à inArray est bien moins efficace que l'appel à hasOwnProperty.

1 votes

C'est aussi O(N^2), non ? Alors que l'approche par dictionnaire ou hasOwnProperty serait probablement O(N*logN).

36voto

Joeytje50 Points 5705

Le plus simple, et le plus rapide (dans Chrome) pour le faire :

Array.prototype.unique = function() {
    var a = [];
    for (var i=0, l=this.length; i<l; i++)
        if (a.indexOf(this[i]) === -1)
            a.push(this[i]);
    return a;
}

Passe simplement en revue chaque élément du tableau, teste si cet élément est déjà dans la liste, et s'il ne l'est pas, le pousse dans le tableau qui est retourné.

Selon JSBench, cette fonction est le plus rapide de ceux que j'ai pu trouver n'importe où. - N'hésitez pas à ajouter les vôtres.

La version non-prototype :

function uniques(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

Triage

Lorsque l'on a également besoin de trier le tableau, la méthode suivante est la plus rapide :

Array.prototype.sortUnique = function() {
    this.sort();
    var last_i;
    for (var i=0;i<this.length;i++)
        if ((last_i = this.lastIndexOf(this[i])) !== i)
            this.splice(i+1, last_i-i);
    return this;
}

ou non-prototype :

function sortUnique(arr) {
    arr.sort();
    var last_i;
    for (var i=0;i<arr.length;i++)
        if ((last_i = arr.lastIndexOf(arr[i])) !== i)
            arr.splice(i+1, last_i-i);
    return arr;
}

C'est aussi plus rapide que la méthode ci-dessus dans la plupart des navigateurs autres que Chrome.

0 votes

Sous Linux, Chrome 55.0.2883 préfère votre arr.unique() et le arrclone2.sortFilter() de swilliams est le plus lent (78% plus lent). Cependant, Firefox 51.0.0 (avec beaucoup d'addons) a swilliams comme le plus rapide (mais toujours plus lent par Ops/sec que tout autre résultat de Chrome) avec mottie's jQuery $.grep(arr, jqFilter) étant le plus lent (46% plus lent). Votre arr.uniq() était 30% plus lent. J'ai exécuté chaque test deux fois et j'ai obtenu des résultats cohérents. Celui de Rafael arr.getUnique() a obtenu la deuxième place dans les deux navigateurs.

0 votes

JsPerf est buggy pour le moment, donc ma modification de ce test n'a pas tout validé, mais elle a permis d'ajouter deux tests : celui de Cocco toUnique() bat celui de Vamsi ES6 list.filter() sur les deux navigateurs, battant swilliams' sortFilter() pour la première place sur FF (sortFilter était 16% plus lent) et battant votre test trié (qui était plus lent de 2%) pour la troisième place sur Chrome.

0 votes

Ah, je n'avais pas compris que ces tests étaient trivialement petits et n'avaient pas vraiment d'importance. Un commentaire à la réponse acceptée décrit ce problème et propose une correction dans un révision au test, dans lequel le code de Rafael est facilement le plus rapide et le code arr.unique de Joetje50 est 98% plus lent. J'ai aussi fait une autre révision comme indiqué dans ce commentaire .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X