Supprimer les valeurs dupliquées du tableau JS [dupliquer]

cette question a déjà une réponse ici:

  • Obtenir toutes les valeurs uniques dans un tableau JavaScript (supprimer les doublons) 59 réponses

j'ai un tableau JavaScript très simple qui peut ou non contenir des doublons.

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

je dois enlever le duplique et place les valeurs uniques dans un nouveau tableau.

je pourrais pointer tous les codes que j'ai essayé mais je pense que c'est inutile parce qu'ils ne fonctionnent pas. J'accepte aussi jQuery solutions.

question similaire:

  • obtenez toutes les valeurs non uniques (c.-à-d.: dupliquer/plus d'une occurrence) dans un tableau
919
demandé sur John Slegers 2012-02-10 18:53:22

30 réponses

Rapide et sale à l'aide de jQuery:

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
    if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});
381
répondu Roman Bataev 2016-12-26 10:53:59

"Smart", mais naïf façon

uniqueArray = a.filter(function(item, pos) {
    return a.indexOf(item) == pos;
})

Fondamentalement, nous parcourir le tableau et, pour chaque élément, vérifiez si la première position de cet élément dans la matrice est égal à la position actuelle. Évidemment, ces deux positions sont différentes pour les éléments dupliqués.

en utilisant le troisième paramètre ("ce tableau") du callback du filtre, nous pouvons éviter une fermeture de la variable du tableau:

uniqueArray = a.filter(function(item, pos, self) {
    return self.indexOf(item) == pos;
})

bien que concis, cet algorithme n'est pas particulièrement efficace pour les grands tableaux (quadratique du temps).

Hashtables à la rescousse

function uniq(a) {
    var seen = {};
    return a.filter(function(item) {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
    });
}

C'est comme ça que c'est fait. L'idée est de placer chaque élément dans une table de hachage, puis de vérifier sa présence instantanément. Cela nous donne un temps linéaire, mais a au moins deux inconvénients:

  • puisque les clés de hachage ne peuvent être que des chaînes en Javascript, ce code ne distingue pas nombres et"chaînes numériques". C'est-à-dire, uniq([1,"1"]) retournera juste [1]
  • pour la même raison, tous les objets seront considérés égaux: uniq([{foo:1},{foo:2}]) retournera juste [{foo:1}] .

cela dit, si vos tableaux ne contiennent que des primitifs et que vous ne vous souciez pas des types (par exemple, ce sont toujours des nombres), cette solution est optimale.

Le meilleur de deux mondes

un universel solution combine les deux approches: il utilise des recherches de hachage pour les primitives et la recherche linéaire pour les objets.

function uniq(a) {
    var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];

    return a.filter(function(item) {
        var type = typeof item;
        if(type in prims)
            return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
        else
            return objs.indexOf(item) >= 0 ? false : objs.push(item);
    });
}

sort / uniq

une autre option consiste à trier le tableau en premier, puis à supprimer chaque élément égal au précédent:

function uniq(a) {
    return a.sort().filter(function(item, pos, ary) {
        return !pos || item != ary[pos - 1];
    })
}

encore une fois, cela ne fonctionne pas avec les objets (parce que tous les objets sont égaux pour sort ). En outre, nous changeons silencieusement le tableau original comme un effet secondaire-pas bon! Cependant, si votre entrée est déjà triée, c'est la voie à suivre (il suffit de supprimer sort de la liste ci-dessus).

Unique par...

parfois, il est souhaité d'uniquifier une liste basée sur des critères autres que l'égalité, par exemple, pour filtrer les objets qui sont différents, mais partagent une propriété. Cela peut être fait avec élégance en passant un rappel. Ce rappel " clé "est appliqué à chaque élément, et les éléments avec des" clés " égales sont supprimés. Puisque key est prévu pour retourner une primitive, la table de hachage fonctionnera très bien ici:

function uniqBy(a, key) {
    var seen = {};
    return a.filter(function(item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    })
}

particulièrement utile key() est JSON.stringify qui permettra de supprimer des objets qui sont physiquement différents, mais le "look" de même:

a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]

Si le key n'est pas primitif, vous devez recourir à la recherche linéaire:

function uniqBy(a, key) {
    var index = [];
    return a.filter(function (item) {
        var k = key(item);
        return index.indexOf(k) >= 0 ? false : index.push(k);
    });
}

ou utilisez L'objet Set dans ES6:

function uniqBy(a, key) {
    var seen = new Set();
    return a.filter(item => {
        var k = key(item);
        return seen.has(k) ? false : seen.add(k);
    });
}

(certaines personnes préfèrent !seen.has(k) && seen.add(k) au lieu de seen.has(k) ? false : seen.add(k) ).

bibliothèques

les deux soulignent et Lo-Dash fournissent uniq méthodes. Leurs algorithmes sont essentiellement similaires au premier extrait ci-dessus et se résument à ceci:

var result = [];
a.forEach(function(item) {
     if(result.indexOf(item) < 0) {
         result.push(item);
     }
});

c'est quadratique, mais il y a de belles choses supplémentaires, comme envelopper natif indexOf , la capacité d'uniqify par une clé ( iteratee dans leur langage), et les optimisations pour les tableaux déjà triés.

si vous utilisez jQuery et que vous ne pouvez rien supporter sans un dollar avant lui, il va comme ceci:

  $.uniqArray = function(a) {
        return $.grep(a, function(item, pos) {
            return $.inArray(item, a) === pos;
        });
  }

qui est, encore une fois, une variation du premier extrait.

Performance

les appels de fonction sont coûteux en Javascript, donc les solutions ci-dessus, comme concis comme ils sont, ne sont pas particulièrement efficaces. Pour une performance maximale, remplacer filter par une boucle et se débarrasser des autres appels de fonction:

function uniq_fast(a) {
    var seen = {};
    var out = [];
    var len = a.length;
    var j = 0;
    for(var i = 0; i < len; i++) {
         var item = a[i];
         if(seen[item] !== 1) {
               seen[item] = 1;
               out[j++] = item;
         }
    }
    return out;
}

ce morceau de code laid fait la même chose que l'extrait #3 ci - dessus, mais un ordre de grandeur plus rapide (à partir de 2017 c'est seulement deux fois plus rapide-les gens de JS core font un excellent travail!)

function uniq(a) {
    var seen = {};
    return a.filter(function(item) {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
    });
}

function uniq_fast(a) {
    var seen = {};
    var out = [];
    var len = a.length;
    var j = 0;
    for(var i = 0; i < len; i++) {
         var item = a[i];
         if(seen[item] !== 1) {
               seen[item] = 1;
               out[j++] = item;
         }
    }
    return out;
}

/////

var r = [0,1,2,3,4,5,6,7,8,9],
    a = [],
    LEN = 1000,
    LOOPS = 1000;

while(LEN--)
    a = a.concat(r);

var d = new Date();
for(var i = 0; i < LOOPS; i++)
    uniq(a);
document.write('<br>uniq, ms/loop: ' + (new Date() - d)/LOOPS)

var d = new Date();
for(var i = 0; i < LOOPS; i++)
    uniq_fast(a);
document.write('<br>uniq_fast, ms/loop: ' + (new Date() - d)/LOOPS)

ES6

ES6 fournit le Set objet, qui rend les choses beaucoup plus facile:

function uniq(a) {
   return Array.from(new Set(a));
}

ou

let uniq = a => [...new Set(a)];

notez que, contrairement à python, les ensembles ES6 sont itérés dans l'ordre d'insertion, donc ce code préserve l'ordre du tableau original.

cependant, si vous avez besoin d'un tableau avec des éléments uniques, pourquoi ne pas utiliser les ensembles dès le début?

générateurs

une version génératrice "lazy" de uniq peut être construite sur la même base:

  • prendre la valeur suivante de l'argument
  • s'il a déjà été vu, sautez-le
  • sinon, donnez-le et ajoutez - le à l'ensemble des valeurs déjà vues

function* uniqIter(a) {
    let seen = new Set();

    for (let x of a) {
        if (!seen.has(x)) {
            seen.add(x);
            yield x;
        }
    }
}

// example:

function* randomsBelow(limit) {
    while (1)
        yield Math.floor(Math.random() * limit);
}

// note that randomsBelow is endless

count = 20;
limit = 30;

for (let r of uniqIter(randomsBelow(limit))) {
    console.log(r);
    if (--count === 0)
        break
}

// exercise for the reader: what happens if we set `limit` less than `count` and why
2342
répondu georg 2018-09-30 23:53:21

s'est lassé de voir tous les mauvais exemples Avec for-loops ou jQuery. Javascript a les outils parfaits pour cela de nos jours: trier, cartographier et réduire.

Uniq réduire tout en gardant ordre existant

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

var uniq = names.reduce(function(a,b){
    if (a.indexOf(b) < 0 ) a.push(b);
    return a;
  },[]);

console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]

// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);

Uniq plus rapide avec tri

il y a probablement des moyens plus rapides mais celui-ci est assez décent.

var uniq = names.slice() // slice makes copy of array before sorting it
  .sort(function(a,b){
    return a > b;
  })
  .reduce(function(a,b){
    if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
    return a;
  },[]); // this empty array becomes the starting value for a

// one liner
return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);

mise à jour 2015: Version ES6:

dans ES6 vous avez des ensembles et Étaler ce qui rend très facile et performant pour enlever tous les doublons:

var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]

trier selon l'occurrence:

Quelqu'un a posé des questions sur l'ordre des résultats basés sur le nombre de noms uniques Il ya:

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

var uniq = names
  .map((name) => {
    return {count: 1, name: name}
  })
  .reduce((a, b) => {
    a[b.name] = (a[b.name] || 0) + b.count
    return a
  }, {})

var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b])

console.log(sorted)
276
répondu Christian Landgren 2015-12-02 22:08:06

Vanilla JS: Supprimer les doublons à l'aide d'un Objet comme un Ensemble

vous pouvez toujours essayer de le mettre dans un objet, puis itérer à travers ses clés:

function remove_duplicates(arr) {
    var obj = {};
    var ret_arr = [];
    for (var i = 0; i < arr.length; i++) {
        obj[arr[i]] = true;
    }
    for (var key in obj) {
        ret_arr.push(key);
    }
    return ret_arr;
}

Vanilla JS: Supprimer les doublons par le suivi de déjà vu valeurs (de l'ordre-sécurité)

ou, pour une version sans risque pour l'ordre, utilisez un objet pour stocker toutes les valeurs précédemment vues, et cochez les valeurs par rapport à elle avant avant de l'ajouter à un tableau.

function remove_duplicates_safe(arr) {
    var seen = {};
    var ret_arr = [];
    for (var i = 0; i < arr.length; i++) {
        if (!(arr[i] in seen)) {
            ret_arr.push(arr[i]);
            seen[arr[i]] = true;
        }
    }
    return ret_arr;

}

ECMAScript 6: Utiliser la nouvelle structure de données (ordre-safe)

ECMAScript 6 ajoute la nouvelle structure de données Set , qui vous permet de stocker des valeurs de n'importe quel type. Set.values renvoie les éléments dans l'ordre d'insertion.

function remove_duplicates_es6(arr) {
    let s = new Set(arr);
    let it = s.values();
    return Array.from(it);
}

exemple d'usage:

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

b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]

c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]

d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
78
répondu Darthfett 2016-10-18 17:11:56

Utiliser Trait De Soulignement.js

c'est une bibliothèque avec un tas de fonctions pour manipuler des tableaux.

c'est la cravate pour aller avec le smoking de jQuery, et L'épine dorsale.js est jarretelle.

_.uniq

_.uniq(array, [isSorted], [iterator]) Alias: unique

Produit une version sans duplicata du array , en utilisant = = = pour tester l'objet égalité. Si vous savez à l'avance que le tableau est trié, passer vrai pour isSorted sera beaucoup plus rapide de l'algorithme. Si vous voulez calculer des éléments uniques basés sur une transformation, passer un iterator fonction.

exemple

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

alert(_.uniq(names, false));

Note: Lo-Dash (an underscore competitor) offre également un comparable .uniq mise en œuvre.

69
répondu Brandon Boone 2014-02-10 00:51:22

une version en ligne simple utilisant le filtre array et les fonctions d'indexOf:

arr = arr.filter (function (value, index, array) { 
    return array.indexOf (value) == index;
});
62
répondu HBP 2016-06-22 07:04:26

vous pouvez simplement le faire en JavaScript, à l'aide du second-paramètre index de la méthode filter :

var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });

ou, en bref de la main

a.filter((v,i) => a.indexOf(v) == i)
47
répondu Ashutosh Jha 2018-01-04 07:10:12

Une seule ligne:

let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);
34
répondu tonkihonks13 2017-08-01 01:39:01

la manière la plus concise de supprimer les doublons d'un tableau en utilisant les fonctions javascript natives est d'utiliser une séquence comme ci-dessous:

vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])

il n'y a pas besoin de slice ni de indexOf dans la fonction de réduction, comme je l'ai vu dans d'autres exemples! il est logique de l'utiliser avec une fonction de filtre:

vals.filter(function(v, i, a){ return i == a.indexOf(v) })

encore une autre façon de faire ES6(2015) qui fonctionne déjà sur quelques navigateurs est:

Array.from(new Set(vals))

ou même en utilisant le spread operator :

[...new Set(vals)]

santé!

30
répondu Ivo 2016-06-14 14:12:57

utiliser Array.filter() comme ceci

var actualArr = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana'];

console.log('Actual Array: ' + actualArr);

var filteredArr = actualArr.filter(function(item, index) {
  if (actualArr.indexOf(item) == index)
    return item;
});

console.log('Filtered Array: ' + filteredArr);

cela peut être raccourci en ES6 à

actualArr.filter((item,index,self) => self.indexOf(item)==index);

Ici est belle explication de Array.filter()

20
répondu Sumit Joshi 2018-02-10 09:37:34

Aller pour cette fois:

var uniqueArray = duplicateArray.filter(function(elem, pos) {
    return duplicateArray.indexOf(elem) == pos;
}); 

maintenant uniqueArray ne contient pas de doublons.

19
répondu Juhan 2016-11-19 07:52:17

le plus simple que j'ai rencontré jusqu'à présent. En es6.

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

 var noDupe = Array.from(new Set(names))

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

17
répondu Deke 2016-12-25 05:18:30

j'avais fait une comparaison détaillée des dupes de l'élimination de quelque autre question, mais ayant remarqué que c'est le lieu réel, je voulais juste le partager ici.

je crois que c'est la meilleure façon de le faire

var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
    reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{}));
console.log(reduced);

OK .. même si celui-ci est O(n) et les autres sont O(N^2), j'étais curieux de voir une comparaison de référence entre ce tableau de réduction / recherche et le filtre / index de combo (je choisis Jeetendras très agréable de mise en œuvre https://stackoverflow.com/a/37441144/4543207 ). Je prépare un tableau d'article 100K rempli avec des entiers positifs aléatoires dans la gamme 0-9999 et et il enlève les doublons. Je répète le test 10 fois et la moyenne des résultats montre qu'ils ne correspondent pas à la performance.

  • Dans firefox v47 réduire et lut : 14.85 ms vs filtre & indexOf : 2836ms
  • Dans chrome v51 réduire et lut : 23.90 ms vs filtre & indexOf : 1066ms

Bon ok jusqu'à présent très bon. Mais faisons-le correctement cette fois dans le style ES6. Il est tellement cool..! Mais à partir de maintenant comment il va fonctionner contre la puissante solution lut est un mystère pour moi. Voyons d'abord le code, puis comparons-le.

var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
    reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()];
console.log(reduced);

Wow c'était court..! Mais comment sur la performance..? C'est très beau... Puisque le poids lourd du filtre / indexOf soulevés au-dessus de nos épaules maintenant, je peux tester une gamme de 1M des éléments aléatoires de nombres entiers positifs dans la plage de 0..99999 pour obtenir une moyenne de 10 essais consécutifs. Je peux dire que cette fois c'est un vrai match. Voir le résultat par vous-même :)

var ranar = [],
     red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
     red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
     avg1 = [],
     avg2 = [],
       ts = 0,
       te = 0,
     res1 = [],
     res2 = [],
     count= 10;
for (var i = 0; i<count; i++){
  ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000));
  ts = performance.now();
  res1 = red1(ranar);
  te = performance.now();
  avg1.push(te-ts);
  ts = performance.now();
  res2 = red2(ranar);
  te = performance.now();
  avg2.push(te-ts);
}

avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;

console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");

lequel utiliserez-vous?.? Bien que pas si vite...! Ne soyez pas trompé. La carte est en déplacement. Maintenant, regardez... dans tous les cas ci-dessus, nous remplissons un tableau de taille n avec des nombres de portée < N. Je veux dire nous avoir un tableau de taille 100 et nous remplissons avec des nombres aléatoires 0..9 Il y a donc des doublons certains et "presque" certainement chaque nombre a un doublon. Et si on remplissait le tableau en taille 100 avec des nombres aléatoires 0..9999. Voyons maintenant Map jouer à la maison. Cette fois, un tableau de 100k articles, mais la plage de nombres aléatoires est 0..100M. Nous ferons 100 tests consécutifs pour faire la moyenne des résultats. OK, nous allons voir les paris..! <- pas de faute de frappe

var ranar = [],
     red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
     red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
     avg1 = [],
     avg2 = [],
       ts = 0,
       te = 0,
     res1 = [],
     res2 = [],
     count= 100;
for (var i = 0; i<count; i++){
  ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000));
  ts = performance.now();
  res1 = red1(ranar);
  te = performance.now();
  avg1.push(te-ts);
  ts = performance.now();
  res2 = red2(ranar);
  te = performance.now();
  avg2.push(te-ts);
}

avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;

console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");

maintenant c'est la remontée spectaculaire de la Carte()..! Peut-être maintenant vous pouvez prendre une meilleure décision lorsque vous souhaitez supprimer les dupes.

Eh bien ok nous sommes tous heureux maintenant. Mais le rôle principal vient toujours en dernier avec quelques applaudissements. Je suis sûr que certains d'entre vous se demandent ce que ferait Set object. Maintenant que nous sommes ouverts à ES6 et que nous savons que Map est le vainqueur des jeux précédents, comparons Map avec Set en finale. Un match typique du Real Madrid contre Barcelone cette fois... ou est-il? Voyons voir qui sera gagner l'el classico :)

var ranar = [],
     red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
     red2 = a => Array.from(new Set(a)),
     avg1 = [],
     avg2 = [],
       ts = 0,
       te = 0,
     res1 = [],
     res2 = [],
     count= 100;
for (var i = 0; i<count; i++){
  ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000));
  ts = performance.now();
  res1 = red1(ranar);
  te = performance.now();
  avg1.push(te-ts);
  ts = performance.now();
  res2 = red2(ranar);
  te = performance.now();
  avg2.push(te-ts);
}

avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;

console.log("map & spread took: " + avg1 + "msec");
console.log("set & A.from took: " + avg2 + "msec");

Wow.. homme..! De façon inattendue, il ne s'est pas avéré être un el classico du tout. Plus comme Barcelone FC contre CA Osasuna :))

16
répondu Redu 2017-05-23 10:31:37

ce qui suit est plus de 80% plus rapide que la méthode jQuery indiquée (voir les essais ci-dessous). C'est une réponse à une question similaire il y a quelques années. Si je rencontre la personne qui l'a proposé à l'origine, je posterai le crédit. Pure JS.

var temp = {};
for (var i = 0; i < array.length; i++)
  temp[array[i]] = true;
var r = [];
for (var k in temp)
  r.push(k);
return r;

ma comparaison de Cas Type: http://jsperf.com/remove-duplicate-array-tests

14
répondu Levi 2018-05-03 09:56:06

Voici une réponse simple à la question.

var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"];
var uniqueNames = [];

    for(var i in names){
        if(uniqueNames.indexOf(names[i]) === -1){
            uniqueNames.push(names[i]);
        }
    }
13
répondu drew7721 2015-03-26 20:26:17

en ECMAScript 6 (alias ECMAScript 2015), Set peut être utilisé pour filtrer les doublons. Ensuite, il peut être reconverti en un tableau en utilisant l'opérateur spread .

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
    unique = [...new Set(names)];
13
répondu Oriol 2016-01-08 12:28:06

Solution 1

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

Solution 2 (utilisant Set)

Array.prototype.unique = function() {
    return Array.from(new Set(this));
}

Test

var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]

Performance

lorsque j'ai testé l'implémentation (avec et sans Set) pour les performances dans chrome, j'ai constaté que celle avec Set est beaucoup plus rapide!

Array.prototype.unique1 = function() {
    var a = [];
    for (i = 0; i < this.length; i++) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }
    return a;
}


Array.prototype.unique2 = function() {
    return Array.from(new Set(this));
}

var x=[];
for(var i=0;i<10000;i++){
	x.push("x"+i);x.push("x"+(i+1));
}

console.time("unique1");
console.log(x.unique1());
console.timeEnd("unique1");



console.time("unique2");
console.log(x.unique2());
console.timeEnd("unique2");
12
répondu ShAkKiR 2018-05-25 07:05:48

une technique simple mais efficace, consiste à utiliser la méthode filter en combinaison avec le filtre function(value, index){ return this.indexOf(value) == index } .

exemple de Code:

var data = [2,3,4,5,5,4];
var filter = function(value, index){ return this.indexOf(value) == index };
var filteredData = data.filter(filter, data );

document.body.innerHTML = '<pre>' + JSON.stringify(filteredData, null, '\t') +  '</pre>';

Voir aussi ce violon .

10
répondu John Slegers 2017-03-29 09:31:39

les réponses supérieures ont une complexité de O(n²) , mais cela peut être fait avec juste O(n) en utilisant un objet comme un hachage:

function getDistinctArray(arr) {
    var dups = {};
    return arr.filter(function(el) {
        var hash = el.valueOf();
        var isDup = dups[hash];
        dups[hash] = true;
        return !isDup;
    });
}

cela fonctionnera pour les chaînes, les nombres et les dates. Si votre tableau contient des objets complexes (i.e., ils doivent être comparés avec === ), la solution ci-dessus ne fonctionnera pas. Vous pouvez obtenir une implémentation O(n) pour les objets en plaçant un drapeau sur l'objet lui-même:

function getDistinctObjArray(arr) {
    var distinctArr = arr.filter(function(el) {
        var isDup = el.inArray;
        el.inArray = true;
        return !isDup;
    });
    distinctArr.forEach(function(el) {
        delete el.inArray;
    });
    return distinctArr;
}
9
répondu gilly3 2013-02-06 22:32:59

voici la méthode simple sans aucune bibliothèque spéciale sont Fonction spéciale,

name_list = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
get_uniq = name_list.filter(function(val,ind) { return name_list.indexOf(val) == ind; })

console.log("Original name list:"+name_list.length, name_list)
console.log("\n Unique name list:"+get_uniq.length, get_uniq)

enter image description here

9
répondu Mohideen ibn Mohammed 2017-08-03 14:18:30

en plus D'être une solution plus simple, plus courte que les réponses actuelles (moins les ES6 à l'avenir), j'ai perf testé ceci et il était beaucoup plus rapide aussi bien:

var uniqueArray = dupeArray.filter(function(item, i, self){
  return self.lastIndexOf(item) == i;
});

un avertissement: Array.latindexof () a été ajouté dans IE9, donc si vous devez aller plus bas que cela, vous devrez chercher ailleurs.

8
répondu csuwldcat 2016-01-13 00:46:58

Ainsi, les options est:

let a = [11,22,11,22];
let b = []


b = [ ...new Set(a) ];     
// b = [11, 22]

b = Array.from( new Set(a))   
// b = [11, 22]

b = a.filter((val,i)=>{
  return a.indexOf(val)==i
})                        
// b = [11, 22]
8
répondu ofir_aghai 2017-03-15 14:26:39

Approche Fonctionnelle Générique

Voici une approche générique et strictement fonctionnelle avec ES2015:

// small, reusable auxiliary functions

const apply = f => a => f(a);

const flip = f => b => a => f(a) (b);

const uncurry = f => (a, b) => f(a) (b);

const push = x => xs => (xs.push(x), xs);

const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);

const some = f => xs => xs.some(apply(f));


// the actual de-duplicate function

const uniqueBy = f => foldl(
   acc => x => some(f(x)) (acc)
    ? acc
    : push(x) (acc)
 ) ([]);


// comparators

const eq = y => x => x === y;

// string equality case insensitive :D
const seqCI = y => x => x.toLowerCase() === y.toLowerCase();


// mock data

const xs = [1,2,3,1,2,3,4];

const ys = ["a", "b", "c", "A", "B", "C", "D"];


console.log( uniqueBy(eq) (xs) );

console.log( uniqueBy(seqCI) (ys) );

nous pouvons facilement dériver unique de unqiueBy ou utiliser l'implémentation plus rapide en utilisant Set s:

const unqiue = uniqueBy(eq);

// const unique = xs => Array.from(new Set(xs));

les Avantages de cette approche:

  • solution générique en utilisant un comparateur de fonction
  • déclarative et succincte de la mise en œuvre
  • réutilisation d'autres petites fonctions génériques

Facteurs De Performance

uniqueBy n'est pas aussi rapide qu'une implémentation impérative avec des boucles, mais elle est beaucoup plus expressive en raison de sa généralité.

si vous identifiez uniqueBy comme la cause d'une pénalité de performance concrète dans votre application, remplacez - le par code optimisé. C'est, écrire votre premier code dans un fonctionnel, déclarative. Par la suite, si vous rencontrez des problèmes de performance, essayez d'optimiser le code aux endroits, qui sont la cause du problème.

consommation de mémoire et collecte des ordures

uniqueBy utilise des mutations ( push(x) (acc) ) cachées à l'intérieur de son corps. Il réutilise l'accumulateur au lieu de le jeter après chaque itération. Cela réduit la mémoire consommation et pression de gaz. Puisque cet effet secondaire est enveloppé à l'intérieur de la fonction, tout à l'extérieur reste pur.

7
répondu ftor 2016-09-09 08:02:47
$(document).ready(function() {

    var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"]

    var arr2=["cat","fish","mango","apple"]

    var uniquevalue=[];
    var seconduniquevalue=[];
    var finalarray=[];

    $.each(arr1,function(key,value){

       if($.inArray (value,uniquevalue) === -1)
       {
           uniquevalue.push(value)

       }

    });

     $.each(arr2,function(key,value){

       if($.inArray (value,seconduniquevalue) === -1)
       {
           seconduniquevalue.push(value)

       }

    });

    $.each(uniquevalue,function(ikey,ivalue){

        $.each(seconduniquevalue,function(ukey,uvalue){

            if( ivalue == uvalue)

            {
                finalarray.push(ivalue);
            }   

        });

    });
    alert(finalarray);
});
4
répondu user3840178 2014-07-15 09:23:48

ici est très simple pour comprendre et travailler n'importe où (même dans le code PhotoshopScript). Check it!

var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");

peoplenames = unique(peoplenames);
alert(peoplenames);

function unique(array){
    var len = array.length;
    for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++) 
        if(array[j] == array[i]){
            array.splice(j,1);
            j--;
            len--;
        }
    return array;
}

//*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
4
répondu bodich 2016-11-11 17:35:23
for (i=0; i<originalArray.length; i++) {  
    if (!newArray.includes(originalArray[i])) {
        newArray.push(originalArray[i]); 
    }
}
4
répondu MBJH 2018-01-17 15:39:20

c'est probablement l'un des moyens les plus rapides pour supprimer en permanence les doublons d'un tableau 10 fois plus rapide que la plupart des fonctions ici. Et 78x plus rapide dans safari

function toUnique(a,b,c){               //array,placeholder,placeholder
 b=a.length;while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
  1. Test: http://jsperf.com/wgu
  2. Démo: http://jsfiddle.net/46S7g /
  3. plus: https://stackoverflow.com/a/25082874/2450730

si vous ne pouvez pas lire le code ci-dessus, demandez, lisez un livre javascript ou voici quelques explications sur le code plus court. https://stackoverflow.com/a/21353032/2450730

3
répondu cocco 2017-05-23 11:47:32

Si, par hasard, vous étiez à l'aide de

D3.js

Vous pourriez le faire

d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]

https://github.com/mbostock/d3/wiki/Arrays#set_values

3
répondu jetpackdata.com 2015-05-31 22:38:53

https://jsfiddle.net/2w0k5tz8 /

function remove_duplicates(array_){
    var ret_array = new Array();
    for (var a = array_.length - 1; a >= 0; a--) {
        for (var b = array_.length - 1; b >= 0; b--) {
            if(array_[a] == array_[b] && a != b){
                delete array_[b];
            }
        };
        if(array_[a] != undefined)
            ret_array.push(array_[a]);
    };
    return ret_array;
}

console.log(remove_duplicates(Array(1,1,1,2,2,2,3,3,3)));

boucle, supprimer les doublons, et créer un support de place de tableau de clones parce que l'index de tableau ne sera pas mis à jour.

boucle en arrière pour une meilleure performance (votre boucle n'a pas besoin de vérifier la longueur de votre tableau)

3
répondu THE AMAZING 2015-08-18 14:45:30

C'était juste une autre solution mais différente du reste.

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  newArr.sort();
  var finalArr = [];
  for(var i = 0;i<newArr.length;i++) {
   if(!(newArr[i] === newArr[i+1] || newArr[i] === newArr[i-1])) {
     finalArr.push(newArr[i]);
   } 
  }
  return finalArr;
}
3
répondu Isaac Pak 2016-06-10 14:23:29