Obtenez 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é l'extrait de code ci-dessous sur l'internet et il fonctionne très bien jusqu'à ce que le tableau a un zéro. J'ai trouvé cet autre script ici sur Donc cela ressemble presque exactement, mais il n'échoue pas.
alors pour m'aider à apprendre, quelqu'un peut-il m'aider à déterminer où le prototype du script 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;
}
autres réponses de question en double:
- supprimer les doublons du tableau JavaScript
question similaire:
- toutes les valeurs avec plus d'une occurrence (i.e.: pas unique) dans un tableau
30 réponses
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
fera une boucle à travers le tableau et ne laissera que les entrées qui passent la fonction de rappel onlyUnique
.
onlyUnique
contrôle, si le la valeur est le premier produit. Si non, il doit être un doublon et ne sera pas copié.
cette solution fonctionne sans bibliothèque supplémentaire comme jQuery ou prototype.js.
fonctionne aussi pour les tableaux à valeurs mixtes.
pour les navigateurs anciens (indexOf
vous pouvez trouver des solutions de travail dans la documentation MDN pour filtre et index 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']
merci à Camilo Martin pour un indice dans le commentaire.
ES6 a un objet natif Set
pour stocker des valeurs uniques. Pour obtenir un tableau avec les valeurs uniques vous pourrait faire maintenant ceci:
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 le tableau, et l'opérateur de propagation ...
transforme le jeu en un tableau. Merci à Lukas Liese pour un indice dans le commentaire.
mise à jour de la réponse pour ES6/ES2015 : en utilisant le Set , la solution de ligne simple est:
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_m suggéré, cela peut également être raccourci en utilisant spread operator , comme
var uniqueItems = [...new Set(items)]
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]
je me rends compte que cette question a déjà plus de 30 réponses. Mais j'ai lu toutes les réponses d'abord et fait ma propre recherche.
j'ai divisé toutes les réponses à 4 solutions possibles:
- utiliser la nouvelle caractéristique ES6:
[...new Set( [1, 1, 2] )];
- Utilisation de l'objet
{ }
pour éviter les doublons - Utiliser le helper tableau
[ ]
- Utiliser
filter + indexOf
voici des exemples de codes trouvés dans les réponses:
utiliser la nouvelle caractéristique ES6: [...new Set( [1, 1, 2] )];
function uniqueArray0(array) {
var result = Array.from(new Set(array));
return result
}
utiliser l'objet { }
pour empêcher 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 helper tableau [ ]
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;
}
Utiliser 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 suis demandé lequel est le plus rapide. J'ai fait exemple de Google Sheet pour les fonctions de test. Note: ECMA 6 n'est pas disponible dans Google Sheets, donc je ne peux pas le tester.
Je m'attendais à ce que le code utilisant l'objet { }
gagne parce qu'il utilise le hash. Donc je suis heureux que les tests ont montré les meilleurs résultats pour cet algorithme dans Chrome et IE. Merci à @rab pour le code .
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 Paul Irish duck punching post - j'ai oublié de donner crédit :p
Un Liner, Pur 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")
avec la syntaxe ES5
list = list.filter(function (x, i, a) {
return a.indexOf(x) == i;
});
compatibilité du navigateur : IE9+
solution la plus courte avec ES6: [...new Set( [1, 1, 2] )];
ou si vous voulez modifier le prototype du tableau (comme dans la question originale):
Array.prototype.getUnique = function() {
return [...new Set( [this] )];
};
EcmaScript 6 est seulement partiellement mis en œuvre dans les navigateurs modernes à l'heure actuelle (Août. 2015), mais Babel est devenu très populaire pour transposer ES6 (et même ES7) retour à ES5. De cette façon, vous pouvez écrire du code ES6 aujourd'hui!
si vous vous demandez ce que signifie le ...
, il est appelé le opérateur de propagation . De MDN : "l'opérateur spread permet d'étendre une expression aux endroits où plusieurs arguments (pour les appels de fonction) ou plusieurs éléments (pour les littérales de tableaux) sont attendus". Parce qu'un ensemble est un itérable (et ne peut avoir que des valeurs uniques), l'opérateur spread développera l'ensemble pour remplir le tableau.
ressources pour apprendre ES6:
- découverte de l'ES6 par le Dr Axel Rauschmayer
- Recherche "ES6" JS bulletins hebdomadaires
- ES6 en profondeur les articles de Mozilla Hacks blog
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)));
le plus simple, et le plus rapide (en Chrome) façon de 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 si ce n'est pas le cas, appuie sur le tableau qui est retourné.
selon jsPerf, cette fonction est le plus rapide de ceux que je pourrais trouver n'importe où - n'hésitez pas à ajouter votre propre bien.
le 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
Lorsqu'il faut aussi trier le tableau, le suivant 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.
PERFORMANCE ONLY! ce code est probablement 10 fois plus rapide que tous les codes ici *fonctionne sur tous les navigateurs et a également le plus faible impact mémoire.... et plus
si vous n'avez pas besoin de réutiliser l'ancien tableau;btw effectuer les autres opérations avant de convertir pour unique ici est probablement le moyen le plus rapide pour ce faire, également très court.
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
alors vous pouvez essayer ceci
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];
function toUnique(a, b, c) { //array,placeholder,placeholder
b = a.length;
while (c = --b)
while (c--) a[b] !== a[c] || a.splice(c, 1);
return a // not needed ;)
}
console.log(toUnique(array));
//[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]
j'ai créé cette fonction en lisant cet article...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array /
je n'aime pas la boucle for. il a de nombreux paramètres.j'aime le tout-- boucle. tout est la manière la plus rapide en boucle dans tous les navigateurs à l'exception de celui que nous aimons tous tellement... chrome.
quoi qu'il en soit j'ai écrit le premier fonction qui utilise tout.Et oui, c'est un peu plus rapide que la fonction trouvée dans l'article.mais pas assez. unique2()
la prochaine étape de l'utilisation moderne de la js. Object.keys
j'ai remplacé l'autre pour boucle par js1.L'objet du 7.touches...
un peu plus rapide et plus court (dans chrome 2X plus rapide) ;). Pas suffisamment!. unique3()
.
à ce moment-là, je pensais à ce dont j'avais vraiment besoin dans ma fonction unique.
je n'ai pas besoin de l'ancien tableau, je veux une fonction rapide.
donc j'ai utilisé 2 tandis que les boucles + splice. unique4()
inutile de dire que j'ai été impressionné.
chrome: les 150 000 opérations habituelles par seconde sont passées à 1 800 000 opérations par seconde.
c'est à dire: de 80 000 op/s vs 3,500,000 op/s
ios: de 18 000 op/s vs de 170 000 op/s
safari: de 80 000 op/s vs 6 000 000 d'op/s
preuve http://jsperf.com/wgu ou mieux utiliser console.temps... microtime... peu importe
unique5()
est juste pour vous montrer ce qui se passe si vous voulez garder l'ancien tableau.
N'utilisez pas Array.prototype
si yu ne sait pas ce que vous faites.
j'ai juste fait beaucoup de copier et de passé.
Utiliser Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})
si vous voulez créer un prototype natif.exemple: https://stackoverflow.com/a/20463021/2450730
Démo http://jsfiddle.net/46S7g /
NOTE: votre vieux tableau est détruit/devient l'unique après cette opération.
si vous ne pouvez pas lire le code ci-dessus demander, lire un livre javascript ou voici quelques explications sur le code plus court. https://stackoverflow.com/a/21353032/2450730
certains utilisent indexOf
... ne le faites pas ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh
pour les matrices vides
!array.length||toUnique(array);
beaucoup de réponses ici peuvent ne pas être utiles pour les débutants. Si le démontage d'un réseau est difficile, connaîtront-ils vraiment la chaîne du prototype, ou même jQuery?
dans les navigateurs modernes, une solution propre et simple est de stocker des données dans un ensemble , qui est 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 retour à un Tableau de sorte que vous avez un accès facile à tous impressionnant de méthodes (fonctions) que les tableaux ont. Il y a aussi d'autres façons de faire la même chose. Mais vous pouvez ne pas avoir besoin de Array.from
du tout, car les ensembles ont beaucoup de fonctionnalités utiles comme forEach .
si vous avez besoin de supporter L'Ancien Internet Explorer, et donc ne pouvez pas utiliser Set, alors une technique simple est de copier des éléments sur un nouveau tableau tout en vérifiant à l'avance s'ils sont 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 rendre ceci instantanément 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 se débarrasser des doublons, nous allons maintenant faire ceci.
var uniqueCars = deduplicate(cars);
la deduplicate(cars)
partie devient la chose que nous avons appelée résultat lorsque la fonction est terminée.
passez-lui le nom de n'importe quel tableau que vous aimez.
ce prototype getUnique
n'est pas tout à fait correct, parce que si j'ai un tableau comme: ["1",1,2,3,4,1,"foo"]
il retournera ["1","2","3","4"]
et "1"
est 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 });
utilisant:
var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();
ci-dessus va produire ["1",2,3,4,1,"foo"]
.
["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;
}, []);
sans extension.prototype (on dit que c'est une mauvaise pratique) ou en utilisant 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, c'est seulement javascript ECMAScript 5+, qui signifie seulement IE9+, mais c'est agréable pour un développement en HTML/JS natif (Windows Store App, Firefox OS, Sencha, Phonegap, Titanium,...).
c'est parce que 0
est une valeur falsy en JavaScript.
this[i]
sera falsy si la valeur du tableau est 0 ou toute autre valeur falsy.
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
}
si vous utilisez Prototype framework il n'est pas nécessaire de faire des boucles 'for', vous pouvez utiliser http://www.prototypejs.org/api/array/uniq comme ceci:
var a = Array.uniq();
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 donc après
uniq ()
j'ai utilisé
size ()
et il y avait mon résultat simple. p. S. Désolé si j'ai mal écrit quelque chose
edit: si vous voulez échapper à des enregistrements non définis, vous pouvez ajouter
compact ()
avant, comme ceci:
var a = Array.compact().uniq();
Je ne sais pas pourquoi Gabriel Silveira a écrit la fonction de cette façon, mais une forme plus simple qui fonctionne pour moi tout aussi bien 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
)
From Shamasis Bhattacharya 's blog (O (2n) time complexity):
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;
};
From Paul Irish 's blog : improvement on 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]
Trouver ensemble unique de valeurs dans la 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]
pour résoudre le problème de l'autre côté, il peut être utile de ne pas avoir de duplicata pendant que vous chargez votre tableau, la façon Set objet le ferait, mais il n'est pas disponible dans tous les navigateurs encore. Il sauve la mémoire et est plus efficace si vous avez besoin de regarder son contenu de nombreuses 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]
étrange que cela n'a pas été suggéré avant.. pour supprimer les doublons par clé 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
))
nous pouvons faire cela 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));
//La sortie sera
uniqueArray = [1,2,3,4,5];
si quelqu'un utilise knockoutjs
ko.utils.arrayGetDistinctValues()
BTW un coup d'oeil à tous les ko.utils.array*
des services publics.
j'ai trouvé que sérialiser 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;
}
vous pouvez également utiliser sucre.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"}]
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]
à l'Origine répondu: fonction jQuery pour obtenir tous les éléments uniques à partir d'un tableau?
ça va marcher.
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;
}
en S'appuyant sur d'autres réponses, voici une autre variante qui prend un drapeau optionnel pour choisir une stratégie (garder la première occurrence ou garder 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]
en utilisant des clés d'objet pour faire 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]);
qui renvoie ["1", 1, 2, 3, 4, "foo", false, null]