web-dev-qa-db-fra.com

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

J'ai une série de chiffres dont je dois 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 la matrice contienne un zéro. J'ai trouvé cet autre script ici sur SO qui lui ressemble presque, mais il n'échoue pas.

Donc, dans le but de m'aider à apprendre, quelqu'un peut-il m'aider à déterminer où le script prototype se passe 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:

987
Mottie

Avec JavaScript 1.6/ECMAScript 5, vous pouvez utiliser la méthode 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 ); // returns ['a', 1, 2, '1']

La méthode native filter parcourt le tableau et ne laisse que les entrées qui transmettent la fonction de rappel donnée onlyUnique.

onlyUnique vérifie si la valeur donnée est la première donnée. Si ce n'est pas le cas, il doit s'agir d'un duplicata 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 prennent pas en charge les méthodes natives filter et indexOf, vous pouvez trouver des solutions dans la documentation MDN pour filter et indexOf .

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

Avec ES6, cela pourrait être réduit à 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']

Merci à Camilo Martin pour le conseil en commentaire. 

ES6 a un objet natif Set pour stocker des valeurs uniques. Pour obtenir un tableau avec des valeurs uniques, procédez comme suit:

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 étendu ... transforme l'ensemble en un tableau. Merci à Lukas Liese pour le commentaire en commentaire.

1876
TLindig

Réponse mise à jour pour ES6/ES2015: À l'aide de Set , la solution monoligne est la suivante:

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

Qui retourne 

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

Comme le suggère le_m , vous pouvez également le raccourcir avec l'opérateur spread , comme

var uniqueItems = [...new Set(items)]
642
A.T.

Vous pouvez également utiliser nderscore.js .

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

qui retournera:

[1, 2, 3, 4]
130
kornfridge

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

Je divise toutes les réponses en 4 solutions possibles:

  1. Utiliser la nouvelle fonctionnalité ES6: [...new Set( [1, 1, 2] )];
  2. Utilisez l'objet { } pour éviter les doublons
  3. Utiliser le tableau auxiliaire [ ]
  4. Utilisez 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    
}

Utilisez l'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 le tableau auxiliaire [ ]

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

Utilisez 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 créé exemple de feuille de calcul Google pour tester les fonctions. Remarque: ECMA 6 n’est pas disponible dans Google Sheets, je ne peux donc pas le tester.

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

Je m'attendais à ce que le code utilisant l'objet { } l'emporte car il utilise le hachage. Je suis donc heureux que les tests aient montré les meilleurs résultats pour cet algorithme sous Chrome et IE. Merci à @rab pour le code .

117
Max Makhrov

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

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

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

50
Mottie

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

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

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

EcmaScript 6 n'est pour le moment que partiellement implémenté dans les navigateurs modernes (août 2015), mais Babel est devenu très populaire pour transpiler ES6 (et même ES7) en ES5. De cette façon, vous pouvez écrire du code ES6 dès aujourd'hui!

Si vous vous demandez ce que signifie le ..., il s'appelle l'opérateur spread . De MDN : «L'opérateur de diffusion permet de développer une expression à des endroits où plusieurs arguments (pour les appels de fonction) ou plusieurs éléments (pour les littéraux de tableau) sont attendus». Etant donné qu'un ensemble est un élément itératif (et ne peut avoir que des valeurs uniques), l'opérateur de diffusion le développera pour remplir le tableau.

Ressources pour apprendre ES6:

45
Torsten Becker

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

32
Pedro L.

Le moyen le plus simple et le plus rapide (sous Chrome) consiste à:

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 tous les éléments du tableau, vérifie si cet élément est déjà dans la liste et, dans le cas contraire, envoie au tableau renvoyé.

Selon jsPerf, cette fonction est la plus rapide de celles que je pourrais trouver nulle part - n'hésitez pas à ajouter la vôtre.

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 devez également trier le tableau, voici 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;
}

Ceci est également plus rapide que la méthode ci-dessus dans la plupart des navigateurs non chromés.

30
Joeytje50

Beaucoup de réponses ici peuvent ne pas être utiles aux débutants. S'il est difficile de duper un tableau, vont-ils vraiment connaître la chaîne de prototypes, ou même jQuery?

Dans les navigateurs modernes, une solution simple et propre consiste à stocker les données dans un Set , conçu pour être une liste de valeurs uniques.

const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
const uniqueCars = Array.from(new Set(cars));

Le Array.from est utile pour convertir le set en tableau, afin que vous ayez facilement accès à toutes les superbes méthodes (fonctionnalités) des tableaux. Il y a aussi d'autres moyens de faire la même chose. Mais vous n’avez peut-être pas besoin de Array.from du tout, car les sets offrent de nombreuses fonctionnalités utiles comme forEach .

Si vous devez prendre en charge l'ancien Internet Explorer et ne pouvez donc pas utiliser Set, une technique simple consiste à copier des éléments dans un nouveau tableau tout en vérifiant au préalable s'ils se trouvent déjà dans le nouveau tableau.

// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];

// Go through each car, one at a time.
cars.forEach(function (car) {
    // The code within the following block runs only if the
    // current car does NOT exist in the uniqueCars list
    // - a.k.a. prevent duplicates
    if (uniqueCars.indexOf(car) === -1) {
        // Since we now know we haven't seen this car before,
        // copy it to the end of the uniqueCars list.
        uniqueCars.Push(car);
    }
});

Pour que cela soit immédiatement réutilisable, mettons-le dans une fonction.

function deduplicate(data) {
    if (data.length > 0) {
        var result = [];

        data.forEach(function (elem) {
            if (result.indexOf(elem) === -1) {
                result.Push(elem);
            }
        });

        return result;
    }
}

Donc, pour éliminer les doublons, nous le ferions maintenant.

var uniqueCars = deduplicate(cars);

La partie deduplicate(cars)devient la chose que nous avons nommée résultat lorsque la fonction est terminée.

Il suffit de lui donner le nom du tableau de votre choix.

24
Seth Holladay
["Defects", "Total", "Days", "City", "Defects"].reduce(function(prev, cur) {
  return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
 }, []);

[0,1,2,0,3,2,1,5].reduce(function(prev, cur) {
  return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
 }, []);
19
sergeyz

Ce prototype getUnique n’est pas totalement correct, car si j’ai un tableau tel que: ["1",1,2,3,4,1,"foo"], il retournera ["1","2","3","4"] et "1" est une chaîne et 1 est un entier; ils sont différents.

Voici une solution correcte:

Array.prototype.unique = function(a){
    return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });

en utilisant:

var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();

Ce qui précède produira ["1",2,3,4,1,"foo"].

17
Gabriel Silveira

Nous pouvons le faire en utilisant les ensembles ES6:

var duplicatedArray = [1,2,3,4,5,1,1,1,2,3,4];
var uniqueArray = Array.from(new Set(duplicatedArray));

// Le résultat sera 

uniqueArray = [1,2,3,4,5];
12
chinmayan

Sans étendre Array.prototype (c'est une mauvaise pratique) ni utiliser jquery/underscore, vous pouvez simplement filter le tableau.

En gardant la dernière occurrence:

    function arrayLastUnique(array) {
        return array.filter(function (a, b, c) {
            // keeps last occurrence
            return c.indexOf(a, b + 1) < 0;
        });
    },

ou première occurrence:

    function arrayFirstUnique(array) {
        return array.filter(function (a, b, c) {
            // keeps first occurrence
            return c.indexOf(a) === b;
        });
    },

Eh bien, il s’agit uniquement de javascript ECMAScript 5+, ce qui signifie uniquement IE9 +, mais c’est bien pour un développement en HTML/JS natif (App Windows Store, Firefox OS, Sencha, Phonegap, Titanium, ...).

12
Cœur

En effet, 0 est une valeur de fausseté en JavaScript.

this[i] sera faux si la valeur du tableau est 0 ou toute autre valeur de faux.

10
Luca Matteis

Si vous utilisez le framework Prototype, il n'est pas nécessaire de faire des boucles "pour", vous pouvez utiliser http://www.prototypejs.org/api/array/uniq comme ceci:

var a = Array.uniq();  

Ce qui produira un tableau dupliqué sans doublons. Je suis tombé sur votre question à la recherche d'une méthode pour compter les enregistrements de tableaux distincts afin qu'après 

uniq ()

J'ai utilisé 

taille()

et il y avait mon résultat simple. p.s. Désolé si j'ai mal tapé quelque chose

edit: si vous voulez échapper à des enregistrements non définis, vous voudrez peut-être ajouter 

compact() 

avant, comme ceci:

var a = Array.compact().uniq();  
10
Decebal
Array.prototype.getUnique = function() {
    var o = {}, a = []
    for (var i = 0; i < this.length; i++) o[this[i]] = 1
    for (var e in o) a.Push(e)
    return a
}
9
ephemient

étrange cela n’a pas été suggéré auparavant .. pour supprimer les doublons par clé d’objet (id ci-dessous) dans un tableau, vous pouvez faire quelque chose comme ceci:

const uniqArray = array.filter((obj, idx, arr) => (
  arr.findIndex((o) => o.id === obj.id) === idx
)) 
6
daviestar

Je ne suis pas sûr de savoir pourquoi Gabriel Silveira a écrit la fonction de cette façon, mais une forme plus simple qui fonctionne aussi bien pour moi et sans la minification est:

Array.prototype.unique = function() {
  return this.filter(function(value, index, array) {
    return array.indexOf(value, index + 1) < 0;
  });
};

ou en CoffeeScript:

Array.prototype.unique = ->
  this.filter( (value, index, array) ->
    array.indexOf(value, index + 1) < 0
  )
6
Dan Fox

Recherche de valeurs de tableau uniques dans une méthode simple

function arrUnique(a){
  var t = [];
  for(var x = 0; x < a.length; x++){
    if(t.indexOf(a[x]) == -1)t.Push(a[x]);
  }
  return t;
}
arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9]
6

De Shamasis Bhattacharya blog de ((O (2n) complexité temporelle):

Array.prototype.unique = function() {
    var o = {}, i, l = this.length, r = [];
    for(i=0; i<l;i+=1) o[this[i]] = this[i];
    for(i in o) r.Push(o[i]);
    return r;
};

Du blog de Paul Irish : amélioration de JQuery .unique() :

(function($){

    var _old = $.unique;

    $.unique = function(arr){

        // do the default behavior only if we got an array of elements
        if (!!arr[0].nodeType){
            return _old.apply(this,arguments);
        } else {
            // reduce the array to contain no dupes via grep/inArray
            return $.grep(arr,function(v,k){
                return $.inArray(v,arr) === k;
            });
        }
    };
})(jQuery);

// in use..
var arr = ['first',7,true,2,7,true,'last','last'];
$.unique(arr); // ["first", 7, true, 2, "last"]

var arr = [1,2,3,4,5,4,3,2,1];
$.unique(arr); // [1, 2, 3, 4, 5]
5
Frosty Z

Pour résoudre le problème dans l'autre sens, il peut être utile de ne pas dupliquer le contenu de votre tableau, comme le ferait l'objet Set , mais il n'est pas encore disponible dans tous les navigateurs. Il économise de la mémoire et est plus efficace si vous devez consulter son contenu plusieurs fois.

Array.prototype.add = function (elem) {
   if (this.indexOf(elem) == -1) {
      this.Push(elem);
   }
}

Échantillon:

set = [];
[1,3,4,1,2,1,3,3,4,1].forEach(function(x) { set.add(x); });

Vous donne set = [1,3,4,2]

5
Le Droid

La magie

a.filter(( t={}, e=>!(t[e]=e in t) )) 

O(n)performance ; nous supposons que votre tableau est en a. Explication ici (+ Jeppe amélioration) 

var a1 = [5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];
var a2 = [[2, 17], [2, 17], [2, 17], [1, 12], [5, 9], [1, 12], [6, 2], [1, 12]];
var a3 = ['Mike', 'Adam','Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];

let nd = (a) => a.filter((t={},e=>!(t[e]=e in t))) 


// print
let c= x => console.log(JSON.stringify(x));             
c( nd(a1) );
c( nd(a2) );
c( nd(a3) );

5
Kamil Kiełczewski

J'ai trouvé que la sérialisation leur clé de hachage m'a aidé à obtenir ce travail pour les objets.

Array.prototype.getUnique = function() {
        var hash = {}, result = [], key; 
        for ( var i = 0, l = this.length; i < l; ++i ) {
            key = JSON.stringify(this[i]);
            if ( !hash.hasOwnProperty(key) ) {
                hash[key] = true;
                result.Push(this[i]);
            }
        }
        return result;
    }
3
Jason

Si quelqu'un utilise knockoutjs

ko.utils.arrayGetDistinctValues()

BTW a regardé tous les utilitaires ko.utils.array*.

3
Torbjörn Nomell

Si vous êtes d'accord avec des dépendances supplémentaires ou si vous avez déjà l'une des bibliothèques dans votre base de code, vous pouvez supprimer les doublons d'un tableau à l'aide de LoDash (ou Underscore).

Utilisation

Si vous ne l'avez pas déjà dans votre base de code, installez-le en utilisant npm:

npm install lodash

Puis utilisez-le comme suit:

import _ from 'lodash';
let idArray = _.uniq ([
    1,
    2,
    3,
    3,
    3
]);
console.dir(idArray);

En dehors:  

[ 1, 2, 3 ]
3
NikeshPathania

Vous pouvez également utiliser sugar.js:

[1,2,2,3,1].unique() // => [1,2,3]

[{id:5, name:"Jay"}, {id:6, name:"Jay"}, {id: 5, name:"Jay"}].unique('id') 
  // => [{id:5, name:"Jay"}, {id:6, name:"Jay"}]
3
kornfridge

Solution basée sur Es6 ...

var arr = [2,3,4,2,3,4,2];
const result = [...new Set(arr)];
console.log(result);
2
Vahid Akhtar

Regarde ça. Jquery fournit la méthode uniq suivante: https://api.jquery.com/jQuery.unique/

var ids_array = []

$.each($(my_elements), function(index, el) {
    var id = $(this).attr("id")
    ids_array.Push(id)
});

var clean_ids_array = jQuery.unique(ids_array)

$.each(clean_ids_array, function(index, id) {
   elment = $("#" + id)   // my uniq element
   // TODO WITH MY ELEMENT
});
2
ilgam

En utilisant des clés d’objet pour créer un tableau unique, j’ai essayé de suivre

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

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


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

uniqueArray(["1",1,2,3,4,1,"foo", false, false, null,1]);

Ce qui retourne ["1", 1, 2, 3, 4, "foo", false, null]

2
rab

Je pense que c'est le moyen le plus simple d'obtenir un élément unique d'un tableau.

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

Si vous avez la puissante méthode reduction disponible ( ≥ 5.1 ), vous pouvez essayer quelque chose comme ceci:

Array.prototype.uniq = function() {
  return this.reduce(function(sofar, cur) {
    return sofar.indexOf(cur) < 0 ? sofar.concat([cur]) : sofar;
  }, []);
};

Ce n’est pas l’implémentation la plus efficace (en raison de la vérification indexOf qui, dans le pire des cas, peut parcourir toute la liste). Si l'efficacité est importante, vous pouvez conserver "l'historique" des occurrences dans une structure à accès aléatoire (par exemple, {}) et les saisir à la place. C’est essentiellement ce que la réponse la plus votée fait, alors jetez-y un exemple.

2
Hunan Rostomyan
[...new Set(duplicates)]

C’est le plus simple et référencé depuis MDN Web Docs.

const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)]) // [2, 3, 4, 5, 6, 7, 32]
2
SumanP

Cela fonctionnera.

function getUnique(a) {
  var b = [a[0]], i, j, tmp;
  for (i = 1; i < a.length; i++) {
    tmp = 1;
    for (j = 0; j < b.length; j++) {
      if (a[i] == b[j]) {
        tmp = 0;
        break;
      }
    }
    if (tmp) {
      b.Push(a[i]);
    }
  }
  return b;
}
2
Darshan

Faites-le avec lodash et la fonction identity lambda, définissez-la simplement avant d'utiliser votre objet

const _ = require('lodash');
...    
_.uniqBy([{a:1,b:2},{a:1,b:2},{a:1,b:3}], v=>v.a.toString()+v.b.toString())
_.uniq([1,2,3,3,'a','a','x'])

et aura:

[{a:1,b:2},{a:1,b:3}]
[1,2,3,'a','x']

(c'est le moyen le plus simple)

2
BazSTR

En vous appuyant sur d’autres réponses, voici une autre variante qui utilise un indicateur facultatif pour choisir une stratégie (conserver la première occurrence ou conserver la dernière):

Sans extension Array.prototype 

function unique(arr, keepLast) {
  return arr.filter(function (value, index, array) {
    return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
  });
};

// Usage
unique(['a', 1, 2, '1', 1, 3, 2, 6]); // -> ['a', 1, 2, '1', 3, 6]
unique(['a', 1, 2, '1', 1, 3, 2, 6], true); // -> ['a', '1', 1, 3, 2, 6]

Extension Array.prototype

Array.prototype.unique = function (keepLast) {
  return this.filter(function (value, index, array) {
    return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
  });
};

// Usage
['a', 1, 2, '1', 1, 3, 2, 6].unique(); // -> ['a', 1, 2, '1', 3, 6]
['a', 1, 2, '1', 1, 3, 2, 6].unique(true); // -> ['a', '1', 1, 3, 2, 6]
2
Mrchief

Vous pouvez également utiliser jQuery

var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4];

// note: jQuery's filter params are opposite of javascript's native implementation :(
var unique = $.makeArray($(a).filter(function(i,itm){ 
    // note: 'index', not 'indexOf'
    return i == $(a).index(itm);
}));

// unique: [1, 5, 6, 4, 2, 3]

A l'origine répondu à: fonction jQuery pour obtenir tous les éléments uniques d'un tableau?

2
Nikola Petkanski

La déduplication nécessite généralement un opérateur d'égalité pour le type donné. Cependant, l'utilisation d'une fonction eq nous empêche d'utiliser un Set pour déterminer les doublons de manière efficace, car Set retombe à ===. Comme vous le savez sûrement, === ne fonctionne pas pour les types de référence. Donc, nous sommes gentils si coincés, non?

La solution consiste simplement à utiliser une fonction de transformation qui nous permet de transformer un type (de référence) en quelque chose que nous pouvons réellement rechercher à l'aide de Set. Nous pourrions utiliser une fonction de hachage, par exemple, ou JSON.stringify la structure de données, si elle ne contient aucune fonction.

Souvent, nous n'avons besoin que d'accéder à une propriété, que nous pouvons ensuite comparer à la place de la référence de Object.

Voici deux combinateurs qui répondent à ces exigences:

const dedupeOn = k => xs => {
  const s = new Set();

  return xs.filter(o =>
    s.has(o[k])
      ? null
      : (s.add(o[k]), o[k]));
};

const dedupeBy = f => xs => {
  const s = new Set();

  return xs.filter(x => {
    const r = f(x);
    
    return s.has(r)
      ? null
      : (s.add(r), x);
  });
};

const xs = [{foo: "a"}, {foo: "b"}, {foo: "A"}, {foo: "b"}, {foo: "c"}];

console.log(
  dedupeOn("foo") (xs)); // [{foo: "a"}, {foo: "b"}, {foo: "A"}, {foo: "c"}]

console.log(
  dedupeBy(o => o.foo.toLowerCase()) (xs)); // [{foo: "a"}, {foo: "b"}, {foo: "c"}]

Avec ces combinateurs, nous sommes extrêmement flexibles dans le traitement de toutes sortes de problèmes de déduplication. Ce n'est pas l'approche du jeûne, mais l'approche la plus expressive et la plus générique.

2
bob

j'ai eu un problème légèrement différent où j'avais besoin de supprimer des objets avec les propriétés en double id d'un tableau. cela a fonctionné ..

let objArr = [ { id: '123' }, { id: '123' }, { id: '456' } ];

objArr = objArr.reduce( ( acc, cur ) => [
    ...acc.filter( ( obj ) => obj.id !== cur.id ), cur
], [] );
2
shunryu111

J'ai une solution qui utilise es6 réduire et trouver des méthodes d'assistance de tableau pour supprimer les doublons.

let numbers = [2,2,3,3,5,6,6];

const removeDups = array => {
  return array.reduce((acc, inc) => {
    if(!acc.find( i => i === inc)) {
       acc.Push(inc);
    }
     return acc;
  },[]);
}

removeDups(numbers); /// [2,3,5,6]
1
tjacks3
Array.prototype.unique = function() {
    var a = [],k = 0,e;
    for(k=0;e=this[k];k++)
      if(a.indexOf(e)==-1)
           a.Push(e);
    return a;
}
[1,2,3,4,33,23,2,3,22,1].unique(); // return [1,2,3,4,33,23,22]
1
user2718726

Je sais que la réponse à cette question est déjà mortelle ... mais .... personne n'a mentionné l'implémentation javascript de linq . Ensuite, la méthode .distinct() peut être utilisée - et cela rend le code super facile à lire.

var Linq = require('linq-es2015');
var distinctValues =  Linq.asEnumerable(testValues)
            .Select(x)
            .distinct()
            .toArray();

var testValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];

var distinctValues = Enumerable.asEnumerable(testValues)
  .distinct()
  .toArray();

console.log(distinctValues);
<script src="https://npmcdn.com/linq-es5/dist/linq.js"></script>

1
pgee70

Créer un tableau de tableaux uniques, en utilisant le champ [2] comme identifiant:

[ [ '497', 'Q0', 'WTX091-B06-138', '0', '1.000000000', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B09-92', '1', '0.866899288', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B09-92', '2', '0.846036819', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B09-57', '3', '0.835025326', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B43-79', '4', '0.765068215', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B43-56', '5', '0.764211464', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B44-448', '6', '0.761701704', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B44-12', '7', '0.761701704', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B49-128', '8', '0.747434800', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B18-17', '9', '0.746724770', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B19-374', '10', '0.733379549', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B19-344', '11', '0.731421782', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B09-92', '12', '0.726450470', 'GROUP001' ],
  [ '497', 'Q0', 'WTX091-B19-174', '13', '0.712757036', 'GROUP001' ] ]
    .filter((val1, idx1, arr) => !!~val1.indexOf(val1[2]) && 
    !(arr.filter((val2, idx2) => !!~val2.indexOf(val1[2]) && 
idx2 < idx1).length));
1
Ali

Celui-ci n'est pas pur, il modifiera le tableau, mais c'est le plus rapide. Si le vôtre est plus rapide, alors s'il vous plaît écrivez dans les commentaires;)

http://jsperf.com/unique-array-webdeb

Array.prototype.uniq = function(){
    for(var i = 0, l = this.length; i < l; ++i){
        var item = this[i];
        var duplicateIdx = this.indexOf(item, i + 1);
        while(duplicateIdx != -1) {
            this.splice(duplicateIdx, 1);
            duplicateIdx = this.indexOf(item, duplicateIdx);
            l--;
        }
    }

    return this;
}

[
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc"
].uniq() //  ["",2,4,"A","abc"]
1
webdeb
var numbers = [1,1,2,3,4,4];

function unique(dupArray) {
    return  dupArray.reduce(function (previous, num){

        if (previous.find(function(item){
            return item == num;
        })) {
            return previous;
        } else {
            previous.Push(num);
            return previous;
        }
    }, [])
}

var check = unique(numbers);
console.log(check);
1
Junaid Khan

Encore une autre solution pour la pile.

J'ai récemment eu besoin de rendre une liste triée unique et je l'ai fait en utilisant un filtre qui garde la trace de l'élément précédent dans un objet tel que

uniqueArray = sortedArray.filter(function(e) { 
    if(e==this.last) 
      return false; 
    this.last=e; return true;  
  },{last:null});
1
pix

Maintenant, en utilisant des ensembles, vous pouvez supprimer les doublons et les reconvertir dans le tableau.

var names = ["Mike","Matt","Nancy", "Matt","Adam","Jenny","Nancy","Carl"];

console.log([...new Set(names)])
1
Krishnadas PC

Vous pouvez utiliser Ramda.js , une bibliothèque javascript fonctionnelle pour faire ceci:

var unique = R.uniq([1, 2, 1, 3, 1, 4])
console.log(unique)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

1
Morris S

Ce script modifie le tableau en filtrant les valeurs dupliquées. Cela fonctionne avec des nombres et des chaînes.

https://jsfiddle.net/qsdL6y5j/1/

    Array.prototype.getUnique = function () {
        var unique = this.filter(function (elem, pos) {
            return this.indexOf(elem) == pos;
        }.bind(this));
        this.length = 0;
        this.splice(0, 0, unique);
    }

    var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
    duplicates.getUnique();
    alert(duplicates);

Cette version vous permet plutôt de renvoyer un nouveau tableau avec une valeur unique en conservant l’original (il suffit de transmettre true).

https://jsfiddle.net/dj7qxyL7/

    Array.prototype.getUnique = function (createArray) {
        createArray = createArray === true ? true : false;
        var temp = JSON.stringify(this);
        temp = JSON.parse(temp);
        if (createArray) {
            var unique = temp.filter(function (elem, pos) {
                return temp.indexOf(elem) == pos;
            }.bind(this));
            return unique;
        }
        else {
            var unique = this.filter(function (elem, pos) {
                return this.indexOf(elem) == pos;
            }.bind(this));
            this.length = 0;
            this.splice(0, 0, unique);
        }
    }

    var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
    console.log('++++ ovveride')
    duplicates.getUnique();
    console.log(duplicates);
    console.log('++++ new array')
    var duplicates2 = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
    var unique = duplicates2.getUnique(true);
    console.log(unique);
    console.log('++++ original')
    console.log(duplicates2);

Browser support:

Feature Chrome  Firefox (Gecko)     Internet Explorer   Opera   Safari
Basic support   (Yes)   1.5 (1.8)   9                   (Yes)   (Yes)
1
GibboK

La version qui accepte le sélecteur, devrait être assez rapide et concise:

function unique(xs, f) {
  var seen = {};
  return xs.filter(function(x) {
    var fx = (f && f(x)) || x;
    return !seen[fx] && (seen[fx] = 1);
  });
}
1
Grozz

Il s'agit d'une fonction ES6 qui supprime les doublons d'un tableau d'objets, en filtrant par la propriété d'objet spécifiée

function dedupe(arr = [], fnCheck = _ => _) {
  const set = new Set();
  let len = arr.length;

  for (let i = 0; i < len; i++) {
    const primitive = fnCheck(arr[i]);
    if (set.has(primitive)) {
      // duplicate, cut it
      arr.splice(i, 1);
      i--;
      len--;
    } else {
      // new item, add it
      set.add(primitive);
    }
  }

  return arr;
}

const test = [
    {video:{slug: "a"}},
    {video:{slug: "a"}},
    {video:{slug: "b"}},
    {video:{slug: "c"}},
    {video:{slug: "c"}}
]
console.log(dedupe(test, x => x.video.slug));

// [{video:{slug: "a"}}, {video:{slug: "b"}}, {video:{slug: "c"}}]
1
Andrei

Pour moi, lorsque vous parlez de valeurs uniques, cela signifie pour moi des valeurs qui apparaissent une et une seule fois dans le jeu de données.

Ce qui suit filtre le tableau de valeurs, en vérifiant que le premier et le dernier index d’une valeur donnée sont égaux. Si l'index est égal, cela signifie que la valeur ne doit apparaître qu'une seule fois.

var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5];

var unique = values.filter(function(value) {
  return values.indexOf(value) === values.lastIndexOf(value);
});

console.log(unique); // [3, 6]

Sur la base des commentaires selon lesquels j'ai mal compris la question, voici une approche alternative qui renverra des valeurs uniques non dupliquées à partir du tableau de valeurs.

var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5];
var unique = values.reduce(function(unique, value) {
  return unique.indexOf(value) === -1 ? unique.concat([value]) : unique;
}, []);

console.log(unique); // [1, 2, 3, 4, 5, 6]

1
fubar

Semblable à la solution @sergeyz, mais plus compact en utilisant davantage de formats abrégés tels que les fonctions de flèche et array.includes. Attention: JSlint va se plaindre à cause de l’utilisation du ou logique et de la virgule. (javascript parfaitement valide cependant)

my_array.reduce((a,k)=>(a.includes(k)||a.Push(k),a),[])
1
John Smith

Beaucoup de gens ont déjà mentionné l'utilisation de ...

[...new Set(arr)];

Et ceci est une excellente solution, mais ma préférence est une solution qui fonctionne avec .filter. À mon avis, le filtre est un moyen plus naturel d’obtenir des valeurs uniques. Vous supprimez efficacement les doublons, et supprimer les éléments d'un tableau correspond exactement au filtre. Il vous permet également d’enchaîner .map, .reduce et d’autres appels .filter. J'ai conçu cette solution ...

const unique = () => {
  let cache;  
  return (elem, index, array) => {
    if (!cache) cache = new Set(array);
    return cache.delete(elem);
  };
};

myArray.filter(unique());

La mise en garde est que vous avez besoin d'une fermeture, mais je pense que c'est un bon compromis. En termes de performances, elle est plus performante que les autres solutions que j'ai déjà publiées et qui utilise .filter, mais moins performante que [...new Set(arr)].

Voir aussi mon paquet github youneek

0
Nizmox

La réponse à l'objet ci-dessus ne semble pas fonctionner pour moi dans mon cas d'utilisation d'Object.

Je l'ai modifié comme suit:

var j = {};

this.forEach( function(v) {
   var typ = typeof v;
   var v = (typ === 'object') ? JSON.stringify(v) : v;

   j[v + '::' + typ] = v;
});

return Object.keys(j).map(function(v){
  if ( v.indexOf('::object') > -1 ) {
    return JSON.parse(j[v]);
  }

  return j[v];
});

Cela semble maintenant fonctionner correctement pour les objets, les tableaux, les tableaux avec des valeurs mélangées, les booléens, etc.

0
user3591464

Cette solution devrait être très rapide et fonctionnera dans de nombreux cas.

  1. Convertir les éléments du tableau indexé en clés d'objet
  2. Utiliser la fonction Object.keys

    var indexArray = ["hi","welcome","welcome",1,-9];
    var keyArray = {};
    indexArray.forEach(function(item){ keyArray[item]=null; });
    var uniqueArray = Object.keys(keyArray);
    
0

Si vous avez un tableau d'objets et que vous voulez une fonction uniqueBy, disons, par un champ id: 

function uniqueBy(field, arr) {
   return arr.reduce((acc, curr) => {
     const exists = acc.find(v => v[field] === curr[field]);
     return exists ? acc : acc.concat(curr);
   }, [])
}
0
Ben

J'ai un exemple simple où nous pouvons supprimer des objets d'un tableau ayant un identifiant répété dans des objets,

  let data = new Array({id: 1},{id: 2},{id: 3},{id: 1},{id: 3});
  let unique = [];
  let tempArr = [];
  console.log('before', data);
  data.forEach((value, index) => {
    if (unique.indexOf(value.id) === -1) {
      unique.Push(value.id);
    } else {
      tempArr.Push(index);    
    }
  });
  tempArr.reverse();
  tempArr.forEach(ele => {
    data.splice(ele, 1);
  });
  console.log(data);
0
Shridhar Sagari

Si l'ordre n'est pas important, nous pouvons créer un hachage et obtenir les clés pour créer un tableau unique.

var ar = [1,3,4,5,5,6,5,6,2,1];
var uarEle = {};
links.forEach(function(a){ uarEle[a] = 1; });
var uar = keys(uarEle)

uar aura les éléments uniques du tableau.

0
Kishore Relangi

Encore une autre réponse, juste parce que j’en ai écrit une pour mon cas d’utilisation spécifique. De toute façon, j’ai été en train de trier le tableau, et si je trie, je peux l’utiliser pour dédupliquer.

Notez que ma sorte traite de mes types de données spécifiques, vous aurez peut-être besoin d'une sorte différente en fonction du type d'éléments que vous avez.

var sortAndDedup = function(array) {
  array.sort(function(a,b){
    if(isNaN(a) && isNaN(b)) { return a > b ? 1 : (a < b ? -1 : 0); }
    if(isNaN(a)) { return 1; }
    if(isNaN(b)) { return -1; }
    return a-b;
  });

  var newArray = [];
  var len = array.length;
  for(var i=0; i<len; i++){
    if(i === 0 || array[i] != array[i-1]){
      newArray.Push(array[i]);
    }
  }
};
0
PaulL

Utilisez .toString () pour les chaînes.

var givenvalues = [1,2,3,3,4,5,6];
var values = [];
for(var i=0; i<givenvalues.length; i++)
{
    if(values.indexOf(givenvalues[i]) == -1)
    {
        values[values.length] = givenvalues[i];
    }
}
0
Phani CR

J'ai regardé le code de Joeytje50 sur jsperf qui a comparé un certain nombre d'alternatives. Son code comportait de nombreuses fautes de frappe mineures, ce qui faisait une différence dans les performances et l'exactitude.

Plus important encore, il teste sur un très petit tableau. J'ai fait un tableau avec 1000 entiers. Chaque nombre entier était 100 fois un nombre entier aléatoire compris entre 0 et 1 000. Cela donne environ 1000/e = 368 doublons en moyenne. Les résultats sont à jsperf .

Il s’agit d’un scénario beaucoup plus réaliste où l’efficacité pourrait être nécessaire. Ces changements apportent des changements dramatiques dans les revendications (spécifiquement, le code présenté comme le plus rapide est loin d'être rapide). Les gagnants évidents sont ceux qui utilisent les techniques de hachage, le meilleur étant

Array.prototype.getUnique3 = function(){
   var u = Object.create(null), a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(this[i] in u) continue;
      a.Push(this[i]);
      u[this[i]] = 1;
   }
   return a.length;
}
0
Roobie Nuby
var a = [1,4,2,7,1,5,9,2,4,7,2]
var b = {}, c = {};
var len = a.length;
for(var i=0;i<len;i++){
  a[i] in c ? delete b[a[i]] : b[a[i]] = true;
  c[a[i]] = true;
} 

// b contains all unique elements
0
rajesh

Vous pouvez utiliser les fonctions d’aide des tableaux, reduction () et certaines () pour obtenir votre résultat. Vérifiez mon extrait de code:

var arrayWithDuplicates = [0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a', '', '', null, null];

var arrayWithUniqueValues = arrayWithDuplicates
                            .reduce((previous, item) => {
                                if(!previous.some(element => element === item)) {
                                    previous.Push(item)
                                }
                                return previous;
                            }, []);

console.log('arrayWithUniqueValues', arrayWithUniqueValues)

0

Pour filtrer les valeurs indéfinies et nulles car vous n'en avez généralement pas besoin.

const uniques = myArray.filter(e => e).filter((e, i, a) => a.indexOf(e) === i);

ou

const uniques = [...new Set(myArray.filter(e => e))];
0
LEMUEL ADANE