Question Obtenir toutes les valeurs uniques dans un tableau JavaScript (supprimer les doublons)


J'ai un tableau de nombres dont j'ai besoin pour m'assurer qu'ils sont uniques. J'ai trouvé l'extrait de code ci-dessous sur Internet et cela fonctionne très bien jusqu'à ce que le tableau ait un zéro dedans. j'ai trouvé cet autre script ici sur SO qui ressemble presque exactement à ça, mais ça n'échoue pas.

Alors, pour m'aider à apprendre, est-ce que quelqu'un peut m'aider à déterminer où le script prototype va mal?

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 de la question en double:

Question similaire:


779
2017-12-25 04:28


origine


Réponses:


Avec JavaScript 1.6 / ECMAScript 5 vous pouvez utiliser le natif filter méthode d'un tableau de la façon 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 ); // returns ['a', 1, 2, '1']

La méthode native filter va boucler dans le tableau et ne laisser 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. Sinon, 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 aussi pour les tableaux avec des types de valeurs mixtes.

Pour les anciens navigateurs (<ie9), qui ne supportent pas les méthodes natives filter et indexOf vous pouvez trouver des solutions de rechange dans la documentation MDN pour filtre et Indice de.

Si vous voulez conserver la dernière occurrence d'une valeur, remplacez simplement indexOf par lastIndexOf.

Avec ES6, il pourrait être raccourci à ceci:

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

// unique is ['a', 1, 2, '1']

Grâce à Camilo Martin pour l'indice dans le commentaire.

ES6 a un objet natif Set pour stocker des valeurs uniques. Pour obtenir un tableau avec des valeurs uniques, vous pouvez le faire maintenant:

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

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

// unique is ['a', 1, 2, '1']

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


1465
2018-01-21 12:46



Réponse mise à jour pour ES6 / ES2015: En utilisant le Ensemble, la solution de ligne unique est:

var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

Quels retours

[4, 5, 6, 3, 2, 23, 1]

Comme le_m suggéré, cela peut également être raccourci en utilisant opérateur de propagation , comme

var uniqueItems = [...new Set(items)]

488
2017-10-14 09:42



Vous pouvez aussi 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]

116
2017-07-11 16:25



Je réalise que cette question a déjà plus de 30 réponses. Mais j'ai d'abord lu toutes les réponses existantes et j'ai fait mes propres recherches.

J'ai divisé toutes les réponses en 4 solutions possibles:

  1. Utiliser la nouvelle fonctionnalité ES6: [...new Set( [1, 1, 2] )];
  2. Utiliser un objet { } pour éviter les doublons
  3. Utiliser un tableau d'aide [ ]
  4. Utilisation filter + indexOf

Voici des exemples de codes trouvés dans les réponses:

Utiliser la nouvelle fonctionnalité ES6: [...new Set( [1, 1, 2] )];

function uniqueArray0(array) {
  var result = Array.from(new Set(array));
  return result    
}

Utiliser un objet { } pour éviter les doublons

function uniqueArray1( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });

  return Object.keys(j).map(function(v){
    return j[v];
  });
} 

Utiliser un tableau d'aide [ ]

function uniqueArray2(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;
}

Utilisation filter + indexOf

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

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

  return unique;
}

Et je me demandais lequel est le plus rapide. j'ai fait échantillon Google Sheet pour tester les fonctions. Remarque: ECMA 6 n'est pas disponible dans Google Sheets, donc je ne peux pas le tester.

Voici le résultat des tests: enter image description here

Je m'attendais à voir ce code en utilisant l'objet { } va gagner parce qu'il utilise le hachage. Je suis donc heureux que les tests ont montré de meilleurs résultats pour cet algorithme dans Chrome et IE. Merci à @rab pour le code.


87
2018-03-27 12:24



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

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

Note: Ce code a été tiré de Le poinçon de canard de Paul Irish - J'ai oublié de donner crédit: P


51
2017-07-12 15:41



One Liner, Pure JavaScript

Avec la syntaxe ES6

list = list.filter((x, i, a) => a.indexOf(x) == i)

x --> item in array
i --> index of item
a --> array reference, (in this case "list")

enter image description here

Avec la syntaxe ES5

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

Compatibilité du navigateur: IE9 +


44
2017-09-01 13:32



La solution la plus courte avec ES6: [...new Set( [1, 1, 2] )];

Ou si vous voulez modifier le prototype Array (comme dans la question d'origine):

Array.prototype.getUnique = function() {
    return [...new Set( [this] )];
};

EcmaScript 6 est seulement partiellement mis en œuvre dans les navigateurs modernes en ce moment (août 2015), mais Babel est devenu très populaire pour le retour ES6 (et même ES7) à ES5. De cette façon, vous pouvez écrire du code ES6 aujourd'hui!

Si vous vous demandez ce que le ... signifie, il est appelé le opérateur de propagation. De MDN: «L'opérateur spread permet de développer une expression dans des endroits où de multiples arguments (pour les appels de fonction) ou plusieurs éléments (pour les littéraux de tableau) sont attendus». Comme un ensemble est itérable (et ne peut avoir que des valeurs uniques), l'opérateur de propagation étend l'ensemble pour remplir le tableau.

Ressources pour l'apprentissage ES6:


39
2018-04-23 12:42



La solution la plus simple:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log([...new Set(arr)]);

Ou:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log(Array.from(new Set(arr)));


31
2018-03-14 22:01



Le plus simple, et le plus rapide (dans Chrome) façon de faire ceci:

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;
}

Parcourt simplement chaque élément du tableau, teste si cet élément est déjà dans la liste, et si ce n'est pas le cas, poussez sur le tableau qui est retourné.

Selon jsPerf, cette fonction est le plus rapide de ceux que j'ai pu trouver n'importe où - N'hésitez pas à ajouter votre propre bien.

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;
}

Tri

Lorsque vous avez également besoin de trier le tableau, ce qui suit est le 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 non-chrome.


30
2018-01-30 00:10