javascript - unicos - Obtenga todos los valores no únicos(es decir, duplicado/más de una ocurrencia) en una matriz
valores repetidos javascript (30)
Encuentra valores únicos de 3 matrices (o más):
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 para array indexOf para navegadores antiguos:
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;
};
}
Solución jQuery usando "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);
en lugar de agregar el ''Array.prototype.indexOf''
Necesito verificar una matriz de JavaScript para ver si hay valores duplicados. ¿Cuál es la forma más fácil de hacer esto? Solo necesito encontrar cuáles son los valores duplicados: en realidad no necesito sus índices o cuántas veces se duplican.
Sé que puedo recorrer la matriz y verificar todos los otros valores para una coincidencia, pero parece que debería haber una manera más fácil ¿Algunas ideas? ¡Gracias!
Pregunta similar:
Encuentra valores duplicados en una matriz
Esta debería ser una de las maneras más cortas de encontrar realmente valores duplicados en una matriz. Como lo solicitó específicamente el OP, esto no elimina duplicados sino que los encuentra .
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])
Esto no necesita clasificación o cualquier marco de terceros. Tampoco necesita bucles manuales. Funciona con todos los valores que indexOf() (o para ser más claros: el operador de comparación estricta ) admite
ACTUALIZADO: Lo siguiente utiliza una estrategia combinada optimizada. Optimiza las búsquedas primitivas para beneficiarse del tiempo de búsqueda de hash O (1) (la ejecución unique
en una matriz de primitivas es O (n)). Las búsquedas de objetos se optimizan al etiquetar los objetos con una ID única mientras se repite, por lo que la identificación de objetos duplicados también es O (1) por elemento y O (n) para toda la lista. La única excepción son los elementos que están congelados, pero son raros y se proporciona un respaldo utilizando una matriz 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;
}();
Si tiene Colecciones ES6 disponibles, entonces hay una versión mucho más simple y significativamente más rápida. (shim para IE9 + y otros navegadores aquí: 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;
}
});
}
Acabo de descubrir una forma sencilla de lograr esto utilizando un filtro de 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);
Aquí es una manera muy ligera y fácil:
var codes = dc_1.split('','');
var i = codes.length;
while (i--) {
if (codes.indexOf(codes[i]) != i) {
codes.splice(i,1);
}
}
Aquí está mi solución simple y de una línea.
Primero no busca elementos únicos, luego hace que la matriz encontrada sea única con el uso de Set.
Así que tenemos una matriz de duplicados al final.
var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];
console.log([...new Set(
array.filter((value, index, self) => self.indexOf(value) !== index))]
);
Código simple con sintaxis ES6 (devuelve una matriz ordenada de duplicados):
let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};
Cómo utilizar:
duplicates([1,2,3,10,10,2,3,3,10]);
Con ES6 (o usando Babel o Typescipt) puedes simplemente hacer:
var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);
Creo que la siguiente es la forma más fácil y rápida de O (n) para lograr exactamente lo que pidió:
function getDuplicates( arr ) {
var i, value;
var all = {};
var duplicates = [];
for( i=0; i<arr.length; i++ ) {
value = arr[i];
if( all[value] ) {
duplicates.push( value );
all[value] = false;
} else if( typeof all[value] == "undefined" ) {
all[value] = true;
}
}
return duplicates;
}
O para ES5 o superior:
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;
}, []);
}
Cuando todo lo que necesita es verificar que no haya duplicados, como se pregunta en esta pregunta , puede usar el método 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
Tenga en cuenta que every()
no funcionan para IE 8 y anteriores.
Uso lastIndexOf()
porque podría ser más eficiente que indexOf()
si las devoluciones de llamada de función realizadas por every()
se realizan en el orden del índice, pero eso no está probado.
En CoffeeScript estoy usando esto:
Array::duplicates = -> not @every((elem, i, array) -> array.lastIndexOf(elem) is i)
[1, 2, 3].duplicates() // false
[1, 2, 1].duplicates() // true
ES6 ofrece la estructura de datos Set, que es básicamente una matriz que no acepta duplicados. Con la estructura de datos de Set, hay una manera muy fácil de encontrar duplicados en una matriz (usando solo un bucle).
Aquí está mi código
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;
}
Esta es mi respuesta del hilo duplicado (!):
Me cansé de ver todos los malos ejemplos con for-loops o jQuery. Javascript tiene las herramientas perfectas para esto hoy en día: ordenar, mapear y reducir.
Encuentra artículos duplicados
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'' ]
Sintaxis más funcional:
@ Dmytro-Laptin señaló que se eliminó algún código. Esta es una versión más compacta del mismo código. Usando algunos trucos de ES6 y funciones de orden superior:
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'' ]
Utilizando 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);
Esto debería conseguirte lo que quieres, solo los duplicados.
function find_duplicates(arr) {
var len=arr.length,
out=[],
counts={};
for (var i=0;i<len;i++) {
var item = arr[i];
counts[item] = counts[item] >= 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.
La siguiente función (una variación de la función eliminarDuplicados ya mencionada) parece hacer el truco, devolviendo test2,1,7,5 para la entrada ["test", "test2", "test2", 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]
Tenga en cuenta que el problema es más extraño en JavaScript que en la mayoría de los otros idiomas, porque una matriz de JavaScript puede contener casi cualquier cosa. Tenga en cuenta que las soluciones que utilizan la clasificación podrían necesitar proporcionar una función de clasificación adecuada, aún no he probado esa ruta.
Esta implementación particular funciona para (al menos) cadenas y números.
function findDuplicates(arr) {
var i,
len=arr.length,
out=[],
obj={};
for (i=0;i<len;i++) {
if (obj[arr[i]] != null) {
if (!obj[arr[i]]) {
out.push(arr[i]);
obj[arr[i]] = 1;
}
} else {
obj[arr[i]] = 0;
}
}
return out;
}
Modificando la solución de @ RaphaelMontanaro, tomando prestado del blog de @Nosredna, esto es lo que podría hacer si solo quiere identificar los elementos duplicados de su matriz.
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;
}
Gracias por la solución elegante, @Nosredna!
No me gustaron la mayoría de las respuestas.
¿Por qué? Demasiado complicado, demasiado código, código ineficiente y muchos no responden a la pregunta, que es encontrar los duplicados (y no dar una matriz sin los duplicados).
La siguiente función devuelve todos los duplicados:
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;
}
Debido a que la mayoría de las veces no sirve para devolver TODOS los duplicados, sino simplemente para indicar qué valores duplicados existen. En ese caso, devuelve una matriz con duplicados únicos ;-)
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);
});
}
Tal vez alguien más piensa lo mismo.
Para resolver lo anterior en O (n) la complejidad del tiempo (sin clasificar).
var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
var obj={};
for(var i=0;i<arr.length;i++){
if(!obj[arr[i]]){
obj[arr[i]]=1;
} else {
obj[arr[i]]=obj[arr[i]]+1;
}
}
var result=[]
for(var key in obj){
if(obj[key]>1){
result.push(Number(key)) // change this to result.push(key) to find duplicate strings in an array
}
}
console.log(result)
Prefiero la forma funcional de hacer esto.
function removeDuplicates(links) {
return _.reduce(links, function(list, elem) {
if (list.indexOf(elem) == -1) {
list.push(elem);
}
return list;
}, []);
}
Esto usa un guión bajo, pero Array tiene una función de reduce
, también
Puede ordenar la matriz y luego ejecutarla y luego ver si el índice siguiente (o anterior) es el mismo que el actual. Suponiendo que el algoritmo de ordenación sea bueno, debería ser menor que 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);
Puedes agregar esta función, o modificarla y agregarla al prototipo Array de 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);
Si quieres eliminar los duplicados, prueba esta gran solución:
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;
}
Fuente: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/
Solo ES5 (es decir, necesita un filtro () polyfill para IE8 e inferior):
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] );
});
Solo para añadir alguna teoría a lo anterior.
Encontrar duplicados tiene un límite inferior de O (n * log (n) en el modelo de comparación. Por lo tanto, teóricamente, no puede hacer nada mejor que ordenar primero y luego revisar la lista de forma secuencial eliminando cualquier duplicado que encuentre.
Si desea encontrar los duplicados en el tiempo esperado lineal (O (n)), podría codificar cada elemento de la lista; Si hay una colisión, elimínelo / etiquételo como un duplicado y continúe.
Usando "incluye" para probar si el elemento ya existe.
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);
<h3>Array with duplicates</h3>
<p>[1, 1, 4, 5, 5]</p>
<h3>Array with distinct elements</h3>
<p>[1, 4, 5]</p>
<h3>duplicate values are</h3>
<p>[1, 5]</p>
utilizando underscore.js
function hasDuplicate(arr){
return (arr.length != _.uniq(arr).length);
}
Forma rápida y elegante mediante la desestructuración y reducción de objetos es6.
Se ejecuta en O (n) (1 iteración sobre la matriz) y no repite valores que aparecen más de 2 veces
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'']
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));
Esta función evita el paso de clasificación y utiliza el método reduce () para enviar duplicados a una nueva matriz si no existe en ella.
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 cuando se agrega al prototyp.chain de 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;});}
Consulte aquí: https://gist.github.com/1305056
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);