Como obter valores exclusivos em uma matriz

Como posso obter uma lista de valores exclusivos em uma matriz? Eu sempre tenho que usar uma segunda matriz ou há algo semelhante ao hashmap do Java em JavaScript?

Eu vou estar usando apenas JavaScript e jQuery . Nenhuma biblioteca adicional pode ser usada.

Já que falei sobre isso nos comentários da resposta do @ Rocket, posso também fornecer um exemplo que não usa bibliotecas. Isso requer duas novas funções de protótipo, 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; } 

Você pode então fazer:

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

Para maior confiabilidade, você pode replace contains com a correção indexOf do MDN e verificar se indexOf cada elemento é igual a -1: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf

Ou para quem procura um one-liner (simples e funcional), compatível com os navegadores atuais :

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

Atualização 18-04-17

Parece que o ‘Array.prototype.includes’ agora tem amplo suporte nas versões mais recentes dos principais navegadores ( compatibilidade )

Atualização 29/07/2015:

Existem planos nos trabalhos para navegadores para suportar um método padronizado ‘Array.prototype.includes’, que embora não responda diretamente a esta pergunta; é frequentemente relacionado.

Uso:

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

Pollyfill ( suporte ao navegador , fonte do 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; } }); } 

Um forro, JavaScript puro

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

insira a descrição da imagem aqui

Com syntax ES5

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

Compatibilidade do Navegador : IE9 +

Aqui está uma solução muito mais limpa para ES6 que eu vejo não está incluída aqui. Utiliza o Set e o operador spread : ...

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

Que retorna [1, 2]

Se você quiser deixar o array original intacto,

você precisa de um segundo array para conter os elementos uniqe do primeiro

A maioria dos navegadores tem o 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 

Nos dias de hoje, você pode usar o tipo de dados Set do ES6 para converter sua matriz em um conjunto exclusivo. Então, se você precisar usar methods de array, poderá transformá-lo novamente em um Array:

 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 o EcmaScript 2016 você pode simplesmente fazer assim.

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

Conjuntos são sempre exclusivos, e usando Array.from() você pode converter um conjunto em um array. Para referência, dê uma olhada nas documentações.

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/from https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects /Conjunto

Solução curta e doce usando segunda matriz;

 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, aqui está uma function única de Array que fiz:

 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] 

Agora no ES6 podemos usar a recém-introduzida function 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)) 

Ele retornará o resultado exclusivo.

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

Você só precisa de vanilla JS para encontrar os únicos com Array.some e Array.reduce. Com a syntax do ES2015, são apenas 62 caracteres.

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

Array.some e Array.reduce são suportados no IE9 + e em outros navegadores. Basta alterar as funções de seta de gordura para funções regulares para suportar em navegadores que não suportam a syntax do 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/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/some https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects / Matriz / Reduzir

A maioria das soluções acima tem uma alta complexidade de tempo de execução.

Aqui está a solução que usa reduce e pode fazer o trabalho no 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]; 

Não é nativo em Javascript, mas muitas bibliotecas têm esse método.

Underscore.js _.uniq(array) ( link ) funciona muito bem ( fonte ).

Rápido, compacto, sem loops nesteds, funciona com qualquer object, não apenas com strings e números, usa um predicado e apenas 5 linhas de código !!

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

Exemplo: para encontrar itens exclusivos por 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 você quiser encontrar o primeiro item exclusivo em vez do último, adicione um check-in found.hasOwnPropery ().

O único problema com as soluções dadas até agora é a eficiência. Se você está preocupado com isso (e você provavelmente deve) você precisa evitar loops nesteds: para * para, filter * indexOf, grep * inArray, todos eles iteram a matriz várias vezes. Você pode implementar um único loop com soluções como esta ou esta

Outro pensamento desta questão. Aqui está o que eu fiz para conseguir isso com menos código.

 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] 

Maneira ES6:

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

Eu tentei esse problema no JS puro. Eu segui os seguintes passos: 1. Classifique a matriz dada, 2. passe pela matriz ordenada, 3. Verifique o valor anterior e o próximo valor com o valor atual

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

Demonstração

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

Tendo em mente que indexOf retornará a primeira ocorrência de um elemento, você pode fazer algo assim:

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

Eu estava pensando se podemos usar a pesquisa linear para eliminar as duplicatas:

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

}

HTML:

  
good avg Type1 Type2

Aqui está a solução de um liner para o problema:

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

Eu tenho a function inigualável do JQuery .

 uniqueValues= jQuery.unique( duplicateValues ); 

Para mais, você pode consultar as Documentações da API jquery.

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