Manière maline mais naïve
uniqueArray = myArray.filter(function(item, pos) {
return myArray.indexOf(item) == pos;
})
Fondamentalement, nous allons parcourir le tableau et, pour chaque élément, vérifiez si la première position de cet élément dans la matrice est égale à la position actuelle. Évidemment, ces deux positions sont différentes pour les éléments en double.
À l'aide du 3e ("array") paramètre du filtre de rappel, nous pouvons éviter une fermeture de la variable du tableau:
uniqueArray = myArray.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).
Les tables de hashage à la rescousse
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
C'est ce qui se fait habituellement. 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 fait gagner du temps, mais a au moins deux inconvénients:
- comme les clés de hachage ne peuvent être des chaînes de caractères en Javascript, ce code ne fait pas la distinction des nombres et des "chaînes numériques". C'est,
uniq([1,"1"])
sera de nouveau juste [1]
- pour la même raison, tous les objets seront considérés comme égaux:
uniq([{foo:1},{foo:2}])
sera de nouveau juste [{foo:1}]
.
Cela dit, si vos tableaux contiennent uniquement des types primaires et vous n'avez pas de soins sur les types (par exemple, c'est toujours des nombres), cette solution est optimale.
Le meilleur de deux mondes
Une solution universelle combine les deux approches: il utilise le hachage des recherches pour les types primaires 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 est de trier le tableau en premier, puis de retirez chaque élément égal au précédent:
function uniq(a) {
return a.sort().filter(function(item, pos) {
return !pos || item != a[pos - 1];
})
}
Encore une fois, cela ne fonctionne pas avec des objets (car tous les objets sont égaux avec sort
). En outre, cette méthode silencieusement les modifications du tableau original comme un effet secondaire - pas bon!!!
Unique par...
Parfois, il est souhaité de uniquify une liste basée sur des critères autres que la simple égalité, par exemple, pour trier des objets qui sont différents, mais qui partagent certaines propriétés. Cela peut être fait avec élégance par le passage d'un rappel, habituellement appelé une "clé". key()
qui est appliquée à chaque élément, et d'éléments égaux "clés" sont supprimés. Depuis key
retour est prévu un primitif, table de hachage, beau travail 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 permet de filtrer les objets à l'identique de la structure:
a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]
87 votes
_.uniq(peoplenames)
résout ce problème lodash.com/docs#uniq10 votes
@ConnorLeech c'est facile avec lodash mais pas de manière optimisée.
0 votes
La meilleure solution est de convertir un tableau en objet, les clés de l'objet étant des éléments du tableau, la valeur de chaque clé étant par exemple "true". Ensuite, il suffit de reconvertir le tableau avec Object.keys(obj_name).
41 votes
L'approche la plus simple (à mon avis) consiste à utiliser l'objet Set qui vous permet de stocker des valeurs uniques de n'importe quel type. En d'autres termes, Set supprimera automatiquement les doublons à notre place.
const names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; let unique = [...new Set(names)]; console.log(unique); // 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl'
11 votes
Il y a trop de Mikes dans le monde - pourquoi ne pas les supprimer ? Nancy s'est fait avoir sur ce point.
0 votes
Il s'agit d'une autre façon d'éliminer les doublons var uniquearr= [] ; names.forEach(function(x){ if(!uniquearr.find(y => y === x)) { uniquearr.push(x) ; } }) ; console.log(uniquearr.toString()) ;
0 votes
Il y a plusieurs façons d'y parvenir. Une belle réf : medium.com/dailyjs/
2 votes
Dans ma solution, je trie les données avant de les filtrer : ` const result = data.sort().filter((v, idx, t) => idx==0 || v != t[idx-1]) ;
0 votes
Le code simple
$.unique(arr)
a fonctionné pour moi0 votes
codegrepper.com/search.php?q=array%20unique%20js
0 votes
L'utilisation de ramda R.uniq(names) résout ce problème. ramdajs.com/docs/#uniq
0 votes
Nous pouvons utiliser l'incombinaison Set avec Array.from comme ci-dessous let arrayWithUniqes = Array.from(new Set(arraWithDups))
0 votes
Qui a marqué ceci comme un [duplicate]...