Comment puis-je obtenir une liste de valeurs uniques dans un tableau? Dois-je toujours utiliser un deuxième tableau ou existe-t-il quelque chose de similaire au hashmap de Java en JavaScript?
Je vais utiliser JavaScript et jQuery only. Aucune bibliothèque supplémentaire ne peut être utilisée.
Puisque j'en ai parlé dans les commentaires de la réponse de @ Rocket, je pourrais aussi bien donner un exemple qui n'utilise aucune bibliothèque. Cela nécessite deux nouvelles fonctions prototypes, contains
et unique
Array.prototype.contains = function(v) {
for(var i = 0; i < this.length; i++) {
if(this[i] === v) return true;
}
return false;
};
Array.prototype.unique = function() {
var arr = [];
for(var i = 0; i < this.length; i++) {
if(!arr.includes(this[i])) {
arr.Push(this[i]);
}
}
return arr;
}
Vous pouvez alors faire:
var duplicates = [1,3,4,2,1,2,3,8];
var uniques = duplicates.unique(); // result = [1,3,4,2,8]
Pour plus de fiabilité, vous pouvez remplacer contains
par indexOf
du MDN et vérifier si chaque élément indexOf
est égal à -1: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
Ou pour ceux qui recherchent un one-liner (simple et fonctionnel), compatible avec les navigateurs actuels:
var a = ["1", "1", "2", "3", "3", "1"];
var unique = a.filter(function(item, i, ar){ return ar.indexOf(item) === i; });
Mise à jour 18-04-17
Il semble que "Array.prototype.includes" bénéficie désormais d'un support étendu dans les dernières versions des principaux navigateurs ( compatibilité ).
Mise à jour du 29/07/2015:
Il est prévu que les navigateurs prennent en charge une méthode standardisée 'Array.prototype.includes' qui, bien que ne répondant pas directement à cette question; est souvent liée.
Usage:
["1", "1", "2", "3", "3", "1"].includes("2"); // true
Pollyfill ( support du navigateur , source de mozilla ):
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
// c. Increase k by 1.
// NOTE: === provides the correct "SameValueZero" comparison needed here.
if (o[k] === searchElement) {
return true;
}
k++;
}
// 8. Return false
return false;
}
});
}
Si vous voulez laisser le tableau d'origine intact,
vous avez besoin d'un second tableau pour contenir les éléments uniqe du premier
La plupart des navigateurs ont Array.prototype.filter
:
var unique= array1.filter(function(itm, i){
return array1.indexOf(itm)== i;
// returns true for only the first instance of itm
});
//if you need a 'shim':
Array.prototype.filter= Array.prototype.filter || function(fun, scope){
var T= this, A= [], i= 0, itm, L= T.length;
if(typeof fun== 'function'){
while(i<L){
if(i in T){
itm= T[i];
if(fun.call(scope, itm, i, T)) A[A.length]= itm;
}
++i;
}
}
return A;
}
Array.prototype.indexOf= Array.prototype.indexOf || function(what, i){
if(!i || typeof i!= 'number') i= 0;
var L= this.length;
while(i<L){
if(this[i]=== what) return i;
++i;
}
return -1;
}
De nos jours, vous pouvez utiliser le type de données Set d'ES6 pour convertir votre tableau en un ensemble unique. Ensuite, si vous devez utiliser des méthodes de tableau, vous pouvez le reconvertir en tableau:
var arr = ["a", "a", "b"];
var uniqueSet = new Set(arr); // {"a", "b"}
var uniqueArr = Array.from(uniqueSet); // ["a", "b"]
//Then continue to use array methods:
uniqueArr.join(", "); // "a, b"
Maintenant, dans ES6, nous pouvons utiliser la nouvelle fonction ES6
var items = [1,1,1,1,3,4,5,2,23,1,4,4,4,2,2,2]
var uniqueItems = Array.from(new Set(items))
Il retournera le résultat unique.
[1, 3, 4, 5, 2, 23]
En utilisant EcmaScript 2016, vous pouvez simplement le faire comme ceci.
var arr = ["a", "a", "b"];
var uniqueArray = Array.from(new Set(arr)); // Unique Array ['a', 'b'];
Les ensembles sont toujours uniques et, à l’aide de Array.from()
, vous pouvez convertir un ensemble en tableau. Pour référence, regardez les documentations.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fromhttps://developer.mozilla.org/en-US/ docs/Web/JavaScript/Référence/Global_Objects/Set
Solution courte et douce utilisant un second tableau;
var axes2=[1,4,5,2,3,1,2,3,4,5,1,3,4];
var distinct_axes2=[];
for(var i=0;i<axes2.length;i++)
{
var str=axes2[i];
if(distinct_axes2.indexOf(str)==-1)
{
distinct_axes2.Push(str);
}
}
console.log("distinct_axes2 : "+distinct_axes2); // distinct_axes2 : 1,4,5,2,3
En utilisant jQuery, voici une fonction unique de Array que j'ai créée:
Array.prototype.unique = function () {
var arr = this;
return $.grep(arr, function (v, i) {
return $.inArray(v, arr) === i;
});
}
console.log([1,2,3,1,2,3].unique()); // [1,2,3]
Vous avez seulement besoin de Vanilla JS pour trouver des pièces uniques avec Array.some et Array.reduce. Avec la syntaxe ES2015, ce n'est que 62 caractères.
a.reduce((c, v) => b.some(w => w === v) ? c : c.concat(v)), b)
Array.some et Array.reduce sont pris en charge par IE9 + et d'autres navigateurs. Il suffit de changer les fonctions de flèche épaisse pour que les fonctions habituelles soient prises en charge dans les navigateurs qui ne prennent pas en charge la syntaxe ES2015.
var a = [1,2,3];
var b = [4,5,6];
// .reduce can return a subset or superset
var uniques = a.reduce(function(c, v){
// .some stops on the first time the function returns true
return (b.some(function(w){ return w === v; }) ?
// if there's a match, return the array "c"
c :
// if there's no match, then add to the end and return the entire array
c.concat(v)}),
// the second param in .reduce is the starting variable. This is will be "c" the first time it runs.
b);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/somehttps://developer.mozilla.org/fr docs/Web/JavaScript/Référence/Global_Objects/Array/Réduire
La majorité des solutions ci-dessus ont une complexité de temps d'exécution élevée.
Voici la solution qui utilise reduce
et peut effectuer le travail en O(n) heure.
Array.prototype.unique = Array.prototype.unique || function() {
var arr = [];
this.reduce(function (hash, num) {
if(typeof hash[num] === 'undefined') {
hash[num] = 1;
arr.Push(num);
}
return hash;
}, {});
return arr;
}
var myArr = [3,1,2,3,3,3];
console.log(myArr.unique()); //[3,1,2];
Remarque:
Cette solution ne dépend pas de réduire. L'idée est de créer une carte d'objets et d'insérer des objets uniques dans le tableau.
Rapide, compact, pas de boucles imbriquées, fonctionne avec n'importe quel objet, pas seulement des chaînes et des nombres, prend un prédicat et seulement 5 lignes de code !!
function findUnique(arr, predicate) {
var found = {};
arr.forEach(d => {
found[predicate(d)] = d;
});
return Object.keys(found).map(key => found[key]);
}
Exemple: Pour trouver des articles uniques par type:
var things = [
{ name: 'charm', type: 'quark'},
{ name: 'strange', type: 'quark'},
{ name: 'proton', type: 'boson'},
];
var result = findUnique(things, d => d.type);
// [
// { name: 'charm', type: 'quark'},
// { name: 'proton', type: 'boson'}
// ]
Si vous voulez qu'il trouve le premier élément unique au lieu du dernier, ajoutez un enregistrement found.hasOwnPropery ().
Vous pouvez entrer un tableau avec des doublons et la méthode ci-dessous renverra un tableau avec des éléments uniques.
function getUniqueArray(array){
var uniqueArray = [];
uniqueArray[0] = array[0];
for(var i = 0; i < array.length; i++){
var isExist = false;
for(var j = 0; j < uniqueArray.length; j++){
if(array[i] == uniqueArray[j]){
isExist = true;
break;
}
else{
isExist = false;
}
}
if(isExist == false){
uniqueArray[uniqueArray.length] = array[i];
}
}
return uniqueArray;
}
vous pouvez utiliser,
let arr1 = [1,2,1,3];
let arr2 = [2,3,4,5,1,2,3];
let arr3 = [...new Set([...arr1,...arr2])];
il vous donnera des éléments uniques,
**> mais il y a un piège,
pour ce "1" et 1 et sont des éléments diff, **
la deuxième option consiste à utiliser la méthode de filtrage sur le tableau.
J'ai essayé ce problème en pur JS . J'ai suivi les étapes suivantes 1. Trier le tableau donné, 2. parcourir le tableau trié, 3. Vérifier les valeurs précédentes et suivantes avec la valeur actuelle
// JS
var inpArr = [1, 5, 5, 4, 3, 3, 2, 2, 2,2, 100, 100, -1];
//sort the given array
inpArr.sort(function(a, b){
return a-b;
});
var finalArr = [];
//loop through the inpArr
for(var i=0; i<inpArr.length; i++){
//check previous and next value
if(inpArr[i-1]!=inpArr[i] && inpArr[i] != inpArr[i+1]){
finalArr.Push(inpArr[i]);
}
}
console.log(finalArr);
Une autre pensée de cette question. Voici ce que j'ai fait pour y parvenir avec moins de code.
var distinctMap = {};
var testArray = ['John', 'John', 'Jason', 'Jason'];
for (var i = 0; i < testArray.length; i++) {
var value = testArray[i];
distinctMap[value] = '';
};
var unique_values = Object.keys(distinctMap);
Array.prototype.unique = function () {
var dictionary = {};
var uniqueValues = [];
for (var i = 0; i < this.length; i++) {
if (dictionary[this[i]] == undefined){
dictionary[this[i]] = i;
uniqueValues.Push(this[i]);
}
}
return uniqueValues;
}
Le seul problème avec les solutions apportées jusqu’à présent est l’efficacité. Si cela vous préoccupe (et vous devriez probablement le faire), vous devez éviter les boucles imbriquées: pour * pour, filter * indexOf, grep * inArray, ils effectuent tous une itération du tableau plusieurs fois. Vous pouvez implémenter une boucle unique avec des solutions telles que this ou this
function findUnique(arr) {
var result = [];
arr.forEach(function (d) {
if (result.indexOf(d) === -1)
result.Push(d);
});
return result;
}
var unique = findUnique([1, 2, 3, 1, 2, 1, 4]); // [1,2,3,4]
Si vous n'avez pas à vous soucier des anciens navigateurs, c'est exactement ce pour quoi les ensembles sont conçus.
L'objet Set vous permet de stocker des valeurs uniques de tout type, que ce soit valeurs primitives ou références d'objet.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
const set1 = new Set([1, 2, 3, 4, 5, 1]);
// returns Set(5) {1, 2, 3, 4, 5}
Sachant que indexOf
renverra la première occurrence d'un élément, vous pouvez faire quelque chose comme ceci:
Array.prototype.unique = function(){
var self = this;
return this.filter(function(elem, index){
return self.indexOf(elem) === index;
})
}
Façon ES6:
const uniq = (arr) => (arr.filter((item, index, arry) => (arry.indexOf(item) === index)));
function findUniques(arr){
let uniques = []
arr.forEach(n => {
if(!uniques.includes(n)){
uniques.Push(n)
}
})
return uniques
}
let arr = ["3", "3", "4", "4", "4", "5", "7", "9", "b", "d", "e", "f", "h", "q", "r", "t", "t"]
findUniques(arr)
// ["3", "4", "5", "7", "9", "b", "d", "e", "f", "h", "q", "r", "t"]