Ottieni tutti i valori non univoci (es .: duplicati / più di un’occorrenza) in un array

Devo controllare una matrice JavaScript per vedere se ci sono valori duplicati. Qual è il modo più semplice per farlo? Ho solo bisogno di trovare quali sono i valori duplicati – non ho effettivamente bisogno dei loro indici o quante volte sono duplicati.

So che posso scorrere l’array e controllare tutti gli altri valori per una corrispondenza, ma sembra che ci dovrebbe essere un modo più semplice. Qualche idea? Grazie!

Domanda simile:

  • Ottieni tutti i valori univoci in un array (rimuovi i duplicati)

È ansible ordinare la matrice, quindi eseguirla e quindi verificare se l’indice successivo (o precedente) è uguale a quello corrente. Supponendo che l’algoritmo di ordinamento sia valido, questo dovrebbe essere inferiore a O (n 2 ):

var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7]; var sorted_arr = arr.slice().sort(); // You can define the comparing function here. // JS by default uses a crappy string compare. // (we use slice to clone the array so the // original array won't be modified) var results = []; for (var i = 0; i < sorted_arr.length - 1; i++) { if (sorted_arr[i + 1] == sorted_arr[i]) { results.push(sorted_arr[i]); } } console.log(results); 

Se vuoi elimare i duplicati, prova questa grande soluzione:

 function eliminateDuplicates(arr) { var i, len = arr.length, out = [], obj = {}; for (i = 0; i < len; i++) { obj[arr[i]] = 0; } for (i in obj) { out.push(i); } return out; } 

Fonte: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/

Questa è la mia risposta dal thread duplicato (!):

Mi sono stancato di vedere tutti i cattivi esempi con for-loops o jQuery. Javascript ha gli strumenti perfetti per questo al giorno d’oggi: ordinare, mappare e ridurre.

Trova oggetti duplicati

 var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'] var uniq = names .map((name) => { return {count: 1, name: name} }) .reduce((a, b) => { a[b.name] = (a[b.name] || 0) + b.count return a }, {}) var duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1) console.log(duplicates) // [ 'Nancy' ] 

Sintassi più funzionale:

@ Dmytro-Laptin ha sottolineato che alcuni codici devono essere rimossi. Questa è una versione più compatta dello stesso codice. Utilizzando alcuni trucchi ES6 e funzioni di ordine superiore:

 const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'] const count = names => names.reduce((a, b) => Object.assign(a, {[b]: (a[b] || 0) + 1}), {}) const duplicates = dict => Object.keys(dict).filter((a) => dict[a] > 1) console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 } console.log(duplicates(count(names))) // [ 'Nancy' ] 

Utilizzando Function.prototype.bind:

  // prep const arr = Array.from('Learn more javascript dude'); const counter = (prev, next) => Object.assign(prev, { [next] : (prev[next] || 0) + 1 }); const singles = function(key){ return this[key] === 1 }; const multiples = function(key){ return this[key] > 1 }; // work const counted = arr.reduce(counter, {}); const filtered = Object.keys(counted).filter(multiples.bind(counted)); //[ "e", "a", "r", " ", "d" ] console.log(filtered); 

Puoi aggiungere questa funzione o modificarla e aggiungerla al prototipo di Array di Javascript:

 Array.prototype.unique = function () { var r = new Array(); o:for(var i = 0, n = this.length; i < n; i++) { for(var x = 0, y = r.length; x < y; x++) { if(r[x]==this[i]) { alert('this is a DUPE!'); continue o; } } r[r.length] = this[i]; } return r; } var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9]; var unique = arr.unique(); alert(unique); 

AGGIORNATO: il seguente utilizza una strategia combinata ottimizzata. Ottimizza le ricerche primitive per beneficiare del tempo di ricerca hash O (1) (l’esecuzione unique su una matrice di primitivi è O (n)). Le ricerche di oggetti sono ottimizzate taggando gli oggetti con un ID univoco mentre itera attraverso così l’identificazione degli oggetti duplicati è anche O (1) per elemento e O (n) per l’intero elenco. L’unica eccezione sono gli elementi che sono congelati, ma quelli sono rari e viene fornito un fallback usando un array e indexOf.

 var unique = function(){ var hasOwn = {}.hasOwnProperty, toString = {}.toString, uids = {}; function uid(){ var key = Math.random().toString(36).slice(2); return key in uids ? uid() : uids[key] = key; } function unique(array){ var strings = {}, numbers = {}, others = {}, tagged = [], failed = [], count = 0, i = array.length, item, type; var id = uid(); while (i--) { item = array[i]; type = typeof item; if (item == null || type !== 'object' && type !== 'function') { // primitive switch (type) { case 'string': strings[item] = true; break; case 'number': numbers[item] = true; break; default: others[item] = item; break; } } else { // object if (!hasOwn.call(item, id)) { try { item[id] = true; tagged[count++] = item; } catch (e){ if (failed.indexOf(item) === -1) failed[failed.length] = item; } } } } // remove the tags while (count--) delete tagged[count][id]; tagged = tagged.concat(failed); count = tagged.length; // append primitives to results for (i in strings) if (hasOwn.call(strings, i)) tagged[count++] = i; for (i in numbers) if (hasOwn.call(numbers, i)) tagged[count++] = +i; for (i in others) if (hasOwn.call(others, i)) tagged[count++] = others[i]; return tagged; } return unique; }(); 

Se disponi di raccolte ES6 disponibili, esiste una versione molto più semplice e significativamente più veloce. (shim per IE9 + e altri browser qui: https://github.com/Benvie/ES6-Harmony-Collections-Shim )

 function unique(array){ var seen = new Set; return array.filter(function(item){ if (!seen.has(item)) { seen.add(item); return true; } }); } 

Trova valori duplicati in una matrice

Questo dovrebbe essere uno dei modi più brevi per trovare effettivamente valori duplicati in un array. Come specificamente richiesto dall’OP, questo non rimuove i duplicati ma li trova .

 var input = [1, 2, 3, 1, 3, 1]; var duplicates = input.reduce(function(acc, el, i, arr) { if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc; }, []); document.write(duplicates); // = 1,3 (actual array == [1, 3]) 

Questo dovrebbe ottenere quello che vuoi, solo i duplicati.

 function find_duplicates(arr) { var len=arr.length, out=[], counts={}; for (var i=0;i= 1 ? counts[item] + 1 : 1; if (counts[item] === 2) { out.push(item); } } return out; } find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order. 

using underscore.js

 function hasDuplicate(arr){ return (arr.length != _.uniq(arr).length); } 
 var a = ["a","a","b","c","c"]; a.filter(function(value,index,self){ return (self.indexOf(value) !== index )}) 
 var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort(); a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;}); 

o quando aggiunto al prototyp.chain di Array

 //copy and paste: without error handling Array.prototype.unique = function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});} 

Vedi qui: https://gist.github.com/1305056

Quando tutto ciò che serve è controllare che non ci siano duplicati come richiesto in questa domanda puoi usare il metodo every() :

 [1, 2, 3].every(function(elem, i, array){return array.lastIndexOf(elem) === i}) // true [1, 2, 1].every(function(elem, i, array){return array.lastIndexOf(elem) === i}) // false 

Nota che every() non funziona con IE 8 e versioni successive.

Io uso lastIndexOf() perché potrebbe essere più efficiente di indexOf() se le richiamate di funzione fatte da every() sono fatte nell’ordine dell’indice, ma ciò non è dimostrato.

In CoffeeScript sto usando questo:

 Array::duplicates = -> not @every((elem, i, array) -> array.lastIndexOf(elem) is i) [1, 2, 3].duplicates() // false [1, 2, 1].duplicates() // true 

Trova valori unici da 3 matrici (o più):

 Array.prototype.unique = function () { var arr = this.sort(), i; // input must be sorted for this to work for( i=arr.length; i--; ) arr[i] === arr[i-1] && arr.splice(i,1); // remove duplicate item return arr; } var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9], arr2 = [1,2,511,12,50], arr3 = [22], unique = arr.concat(arr2, arr3).unique(); console.log(unique); // [22, 50, 12, 511, 2, 1, 9, 5, 8, 7, 3, 6, 4] 

Solo un polyfill per l’array indexOf per i vecchi browser:

 if (!Array.prototype.indexOf){ Array.prototype.indexOf = function(elt /*, from*/){ var len = this.length >>> 0; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) from += len; for (; from < len; from++){ if (from in this && this[from] === elt) return from; } return -1; }; } 

soluzione jQuery utilizzando "inArray":

 if( $.inArray(this[i], arr) == -1 ) 

ES2015

 var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,22], arr2 = [1,2,511,12,50], arr3 = [22], unique; // Combine all the arrays to a single one unique = arr.concat(arr2, arr3); // create a new (dirty) Array with only the unique items unique = unique.map((item,i) => unique.includes(item, i+1) ? item : '' ) // Cleanup - remove duplicate & empty items items unique = [...new Set(unique)].filter(n => n); console.log(unique); 

Codice semplice con syntax ES6 (restituisce array ordinati di duplicati):

 let duplicates = a => {d=[]; a.sort((a,b) => ab).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d}; 

Come usare:

 duplicates([1,2,3,10,10,2,3,3,10]); 

La seguente funzione (una variante della funzione deleteDuplicates già menzionata) sembra fare il trucco, restituendo test2,1,7,5 per l’input [“test”, “test2”, “test2”, 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

Nota che il problema è sconosciuto in JavaScript rispetto alla maggior parte degli altri linguaggi, perché un array JavaScript può contenere praticamente qualsiasi cosa. Si noti che le soluzioni che utilizzano l’ordinamento potrebbero dover fornire una funzione di ordinamento appropriata: non ho ancora provato questa strada.

Questa particolare implementazione funziona per (almeno) stringhe e numeri.

 function findDuplicates(arr) { var i, len=arr.length, out=[], obj={}; for (i=0;i 

Ecco un modo molto semplice e leggero:

 var codes = dc_1.split(','); var i = codes.length; while (i--) { if (codes.indexOf(codes[i]) != i) { codes.splice(i,1); } } 
 var arr = [2, 1, 2, 2, 4, 4, 2, 5]; function returnDuplicates(arr) { return arr.reduce(function(dupes, val, i) { if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) { dupes.push(val); } return dupes; }, []); } alert(returnDuplicates(arr)); 

Usando “include” per verificare se l’elemento esiste già.

 var arr = [1, 1, 4, 5, 5], darr = [], duplicates = []; for(var i = 0; i < arr.length; i++){ if(darr.includes(arr[i]) && !duplicates.includes(arr[i])) duplicates.push(arr[i]) else darr.push(arr[i]); } console.log(duplicates); 
 

Array with duplicates

[1, 1, 4, 5, 5]

Array with distinct elements

[1, 4, 5]

duplicate values are

[1, 5]

ES6 offre la struttura di dati Set che è fondamentalmente una matrice che non accetta duplicati. Con la struttura dei dati Set, c’è un modo molto semplice per trovare duplicati in un array (usando solo un loop).

Ecco il mio codice

 function findDuplicate(arr) { var set = new Set(); var duplicates = new Set(); for (let i = 0; i< arr.length; i++) { var size = set.size; set.add(arr[i]); if (set.size === size) { duplicates.add(arr[i]); } } return duplicates; } 

Con ES6 (o usando Babel o Typescipt) puoi semplicemente fare:

 var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1); 

https://es6console.com/j58euhbt/

Ho appena trovato un modo semplice per raggiungere questo objective utilizzando un filtro Array

  var list = [9, 9, 111, 2, 3, 4, 4, 5, 7]; // Filter 1: to find all duplicates elements var duplicates = list.filter(function(value,index,self) { return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index; }); console.log(duplicates); 

Modo veloce ed elegante utilizzando l’object 6 destrutturazione e riduzione

Funziona in O (n) (1 iterazione sull’array) e non ripete i valori che appaiono più di 2 volte

 const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd'] const { dup } = arr.reduce( (acc, curr) => { acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1 if (acc.items[curr] === 2) acc.dup.push(curr) return acc }, { items: {}, dup: [] }, ) console.log(dup) // ['hi', 'bye'] 

Solo per aggiungere qualche teoria a quanto sopra.

La ricerca di duplicati ha un limite inferiore di O (n * log (n) nel modello di confronto, quindi, in teoria, non si può fare meglio del primo ordinamento, quindi scorrere l’elenco in sequenza rimuovendo eventuali duplicati che si trovano.

Se si desidera trovare i duplicati in tempo lineare (O (n)), è ansible eseguire un hash di ogni elemento della lista; se c’è una collisione, rimuovila / etichettala come duplicata e continua.

Solo ES5 (vale a dire, necessita di un filtro () polyfill per IE8 e di seguito):

 var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ]; arrayToFilter. sort(). filter( function(me,i,arr){ return (i===0) || ( me !== arr[i-1] ); }); 
 var input = ['a', 'b', 'a', 'c', 'c'], duplicates = [], i, j; for (i = 0, j = input.length; i < j; i++) { if (duplicates.indexOf(input[i]) === -1 && input.indexOf(input[i], i+1) !== -1) { duplicates.push(input[i]); } } console.log(duplicates); 

Penso che il seguito sia il modo più semplice e veloce O (n) per realizzare esattamente quello che hai chiesto:

 function getDuplicates( arr ) { var i, value; var all = {}; var duplicates = []; for( i=0; i 

O per ES5 o superiore:

 function getDuplicates( arr ) { var all = {}; return arr.reduce(function( duplicates, value ) { if( all[value] ) { duplicates.push(value); all[value] = false; } else if( typeof all[value] == "undefined" ) { all[value] = true; } return duplicates; }, []); } 

Modificando la soluzione @ RaphaelMontanaro, prendendo a prestito dal blog di @ Nosredna, ecco cosa potresti fare se vuoi solo identificare gli elementi duplicati dal tuo array.

 function identifyDuplicatesFromArray(arr) { var i; var len = arr.length; var obj = {}; var duplicates = []; for (i = 0; i < len; i++) { if (!obj[arr[i]]) { obj[arr[i]] = {}; } else { duplicates.push(arr[i]); } } return duplicates; } 

Grazie per l'elegante soluzione, @Nosredna!

Non mi piacevano molte risposte.

Perché? Troppo complicato, troppo codice, codice inefficiente e molti non rispondono alla domanda, ovvero trovare i duplicati (e non dare una matrice senza i duplicati).

La funzione successiva restituisce tutti i duplicati:

 function GetDuplicates(arr) { var i, out=[], obj={}; for (i=0; i < arr.length; i++) obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]); return out; } 

Poiché la maggior parte delle volte è inutile restituire TUTTI i duplicati, ma solo per sapere quali sono i valori duplicati esistenti. In tal caso si restituisce un array con duplicati unici 😉

 function GetDuplicates(arr) { var i, out=[], obj={}; for (i=0; i < arr.length; i++) obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]); return GetUnique(out); } function GetUnique(arr) { return $.grep(arr, function(elem, index) { return index == $.inArray(elem, arr); }); } 

Forse qualcun altro pensa lo stesso.

Preferisco il modo di farlo.

 function removeDuplicates(links) { return _.reduce(links, function(list, elem) { if (list.indexOf(elem) == -1) { list.push(elem); } return list; }, []); } 

Questo usa il carattere di sottolineatura, ma anche l’Array ha una funzione di reduce

Per risolvere quanto sopra nella complessità del tempo O (n) (senza ordinamento).

 var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7]; var obj={}; for(var i=0;i1){ result.push(Number(key)) // change this to result.push(key) to find duplicate strings in an array } } console.log(result) 

Questo è probabilmente uno dei modi più veloci per rimuovere in modo permanente i duplicati da un array 10 volte più veloce rispetto alla maggior parte delle funzioni qui. & 78x più veloce in safari

 function toUnique(a,b,c){//array,placeholder,placeholder b=a.length; while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1) } var array=[1,2,3,4,5,6,7,8,9,0,1,2,1]; toUnique(array); console.log(array); 
  1. Prova: http://jsperf.com/wgu
  2. Demo: http://jsfiddle.net/46S7g/
  3. Altro: https://stackoverflow.com/a/25082874/2450730

se non riesci a leggere il codice sopra, chiedi, leggi un libro javascript o qui ci sono alcune spiegazioni sul codice più breve. https://stackoverflow.com/a/21353032/2450730

EDIT Come indicato nei commenti questa funzione restituisce un array con uniques, la domanda tuttavia chiede di trovare i duplicati. in tal caso una semplice modifica a questa funzione consente di spostare i duplicati in una matrice, quindi utilizzando la funzione precedente per toUnique rimuove i duplicati dei duplicati.

 function theDuplicates(a,b,c,d){//array,placeholder,placeholder b=a.length,d=[]; while(c=--b)while(c--)a[b]!==a[c]||d.push(a.splice(c,1)) } var array=[1,2,3,4,5,6,7,8,9,0,1,2,1]; toUnique(theDuplicates(array));