Come ottenere valori univoci in un array

Come posso ottenere un elenco di valori univoci in un array? Devo sempre usare un secondo array o c’è qualcosa di simile all’hashmap di java in JavaScript?

Utilizzerò solo JavaScript e jQuery . Non è ansible utilizzare librerie aggiuntive.

Da quando ne ho parlato nei commenti per la risposta di @ Rocket, potrei anche fornire un esempio che non usa librerie. Ciò richiede due nuove funzioni di prototipo, contains e 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; } 

Puoi quindi fare:

 var duplicates = [1,3,4,2,1,2,3,8]; var uniques = duplicates.unique(); // result = [1,3,4,2,8] 

Per maggiore affidabilità, è ansible sostituire contains con indexOf shim di MDN e verificare se indexOf ogni elemento è uguale a -1: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf

O per chi cerca un one-liner (semplice e funzionale), compatibile con i browser attuali :

 var a = ["1", "1", "2", "3", "3", "1"]; var unique = a.filter(function(item, i, ar){ return ar.indexOf(item) === i; }); 

Aggiornamento 18-04-17

Sembra che “Array.prototype.includes” ora abbia un supporto diffuso nelle ultime versioni dei browser principali ( compatibilità )

Aggiornamento del 29/07/2015:

Ci sono piani nei lavori per i browser per supportare un metodo standardizzato “Array.prototype.includes”, che sebbene non risponda direttamente a questa domanda; è spesso correlato.

Uso:

 ["1", "1", "2", "3", "3", "1"].includes("2"); // true 

Pollyfill ( supporto browser , fonte da 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; } }); } 

One Liner, Pure JavaScript

Con syntax 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") 

inserisci la descrizione dell'immagine qui

Con syntax ES5

 list = list.filter(function (x, i, a) { return a.indexOf(x) == i; }); 

Compatibilità del browser : IE9 +

Ecco una soluzione molto più pulita per ES6 che vedo non è inclusa qui. Usa il set e l’ operatore di spread : ...

 var a = [1, 1, 2]; [... new Set(a)] 

Che restituisce [1, 2]

Se vuoi lasciare intatto l’array originale,

è necessario un secondo array per contenere gli elementi uniqe del primo

La maggior parte dei browser ha 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 

Al giorno d’oggi, puoi usare il tipo di dati Set di ES6 per convertire la tua matrice in un Set unico. Quindi, se è necessario utilizzare i metodi dell’array, è ansible trasformarlo in una matrice:

 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" 

Usando EcmaScript 2016 puoi semplicemente farlo in questo modo.

  var arr = ["a", "a", "b"]; var uniqueArray = Array.from(new Set(arr)); // Unique Array ['a', 'b']; 

I set sono sempre unici e usando Array.from() puoi convertire un Set in un array. Per riferimento date un’occhiata alle documentazioni.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects /Impostato

Soluzione corta e dolce con secondo array;

 var axes2=[1,4,5,2,3,1,2,3,4,5,1,3,4]; var distinct_axes2=[]; for(var i=0;i 

Usando jQuery, ecco una funzione unica di Array che ho creato:

 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] 

Ora in ES6 possiamo usare la funzione ES6 appena introdotta

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

Restituirà il risultato unico.

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

Hai solo bisogno di JS vaniglia per trovare gli unici con Array.some e Array.reduce. Con la syntax ES2015 ha solo 62 caratteri.

 a.reduce((c, v) => b.some(w => w === v) ? c : c.concat(v)), b) 

Array.some e Array.reduce sono supportati in IE9 + e altri browser. Basta cambiare le funzioni di freccia grossa per le funzioni regolari per supportare nei browser che non supportano la syntax 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/some https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects / Array / Riduzione

La maggior parte delle soluzioni di cui sopra ha una complessità temporale elevata.

Ecco la soluzione che utilizza reduce e può fare il lavoro in tempo O (n).

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

Non nativo in Javascript, ma molte librerie hanno questo metodo.

Il file _.uniq(array) ( link ) di Underscore.js funziona abbastanza bene ( fonte ).

Veloce, compatto, senza loop nidificati, funziona con qualsiasi object non solo stringhe e numeri, prende un predicato e solo 5 linee di codice !!

 function findUnique(arr, predicate) { var found = {}; arr.forEach(d => { found[predicate(d)] = d; }); return Object.keys(found).map(key => found[key]); } 

Esempio: per trovare oggetti unici per tipo:

 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'} // ] 

Se vuoi che trovi il primo object unico invece dell’ultimo aggiungi un found.hasOwnPropery () controlla lì.

L’unico problema con le soluzioni date finora è l’efficienza. Se sei preoccupato di questo (e probabilmente dovresti) devi evitare cicli annidati: per * per, filter * indexOf, grep * inArray, tutti ripetono l’array più volte. È ansible implementare un singolo ciclo con soluzioni come questa o questa

Un altro pensiero di questa domanda. Ecco cosa ho fatto per ottenere questo con meno codice.

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

Modo ES6:

 const uniq = (arr) => (arr.filter((item, index, arry) => (arry.indexOf(item) === index))); 

Ho provato questo problema in puro JS. Ho seguito i seguenti passaggi 1. Ordinare l’array specificato, 2. passare attraverso l’array ordinato, 3. Verificare il valore precedente e il valore successivo con il valore corrente

 // 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 ab; }); var finalArr = []; //loop through the inpArr for(var i=0; i 

dimostrazione

 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"] 

Tenendo presente che indexOf restituirà la prima occorrenza di un elemento, puoi fare qualcosa di simile a questo:

 Array.prototype.unique = function(){ var self = this; return this.filter(function(elem, index){ return self.indexOf(elem) === index; }) } 

Stavo solo pensando se possiamo usare la ricerca lineare per eliminare i duplicati:

 JavaScript: function getUniqueRadios() { var x=document.getElementById("QnA"); var ansArray = new Array(); var prev; for (var i=0;i 

}

HTML:

  
good avg Type1 Type2

Ecco l’unica soluzione di linea per il problema:

 var seriesValues = [120, 120, 120, 120]; seriesValues = seriesValues.filter((value, index, seriesValues) => (seriesValues.slice(0, index)).indexOf(value) === -1); console.log(seriesValues); 

ho integrato la funzione JQuery Unique .

 uniqueValues= jQuery.unique( duplicateValues ); 

Per ulteriori informazioni puoi fare riferimento alle Documentazioni API di jquery.

http://api.jquery.com/jquery.unique/