Pregunta Cómo combinar dos matrices en JavaScript y quitar elementos duplicados


Tengo dos matrices de JavaScript:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

Quiero que la salida sea:

var array3 = ["Vijendra","Singh","Shakya"];

La matriz de salida debe tener palabras repetidas eliminadas.

¿Cómo combino dos matrices en JavaScript para que solo obtenga los elementos únicos de cada matriz en el mismo orden en que se insertaron en las matrices originales?


976
2017-10-18 08:34


origen


Respuestas:


Simplemente fusionar las matrices (sin eliminar duplicados)

Uso de la versión ES5 Array.concat:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var array3 = array1.concat(array2); // Merges both arrays
// [ 'Vijendra', 'Singh', 'Singh', 'Shakya' ]

Uso de la versión ES6 desestructuración

const array1 = ["Vijendra","Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = [...array1, ...array2];

Ya que no existe una forma 'integrada' para eliminar duplicados (ECMA-262 en realidad tiene Array.forEach lo cual sería genial para esto), tenemos que hacerlo de forma manual:

Array.prototype.unique = function() {
    var a = this.concat();
    for(var i=0; i<a.length; ++i) {
        for(var j=i+1; j<a.length; ++j) {
            if(a[i] === a[j])
                a.splice(j--, 1);
        }
    }

    return a;
};

Entonces, para usarlo:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = array1.concat(array2).unique(); 

Esto también preservará el orden de las matrices (es decir, no se necesita clasificación).

Dado que muchas personas están molestas por el aumento de prototipo de Array.prototype y for in bucles, aquí hay una forma menos invasiva de usarlo:

function arrayUnique(array) {
    var a = array.concat();
    for(var i=0; i<a.length; ++i) {
        for(var j=i+1; j<a.length; ++j) {
            if(a[i] === a[j])
                a.splice(j--, 1);
        }
    }

    return a;
}

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
    // Merges both arrays and gets unique items
var array3 = arrayUnique(array1.concat(array2));

Para aquellos que tienen la suerte de trabajar con navegadores donde ES5 está disponible, puede usar Object.defineProperty Me gusta esto:

Object.defineProperty(Array.prototype, 'unique', {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        var a = this.concat();
        for(var i=0; i<a.length; ++i) {
            for(var j=i+1; j<a.length; ++j) {
                if(a[i] === a[j])
                    a.splice(j--, 1);
            }
        }

        return a;
    }
});

1233
2017-10-18 08:42



Con Underscore.js o Lo-Dash puedes hacer:

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]

http://underscorejs.org/#union

http://lodash.com/docs#union


510
2018-05-08 13:24



Primero concatene las dos matrices, luego, filtre solo los elementos únicos.

var a = [1, 2, 3], b = [101, 2, 1, 10];
var c = a.concat(b);
var d = c.filter(function (item, pos) {return c.indexOf(item) == pos});

// d is [1,2,3,101,10]

http://jsfiddle.net/simo/98622/

Editar

Según lo sugerido por @Dmitry (ver el segundo comentario a continuación), una solución más eficiente en cuanto al rendimiento sería filtrar los elementos únicos en b antes de concatenar con a

var a = [1, 2, 3], b = [101, 2, 1, 10];
var c = a.concat(b.filter(function (item) {
    return a.indexOf(item) < 0;
}));

// d is [1,2,3,101,10]

193
2018-04-15 10:08



Esta es una solución de ECMAScript 6 que usa operador de propagación y genéricos de matriz.

Actualmente solo funciona con Firefox, y posiblemente con la vista previa técnica de Internet Explorer.

Pero si usas Babel, puedes tenerlo ahora

// Input: [ [1, 2, 3], [101, 2, 1, 10], [2, 1] ]
// Output: [1, 2, 3, 101, 10]
function mergeDedupe(arr)
{
  return [...new Set([].concat(...arr))];
}

119
2017-12-27 06:28



ES6

array1.push(...array2) // => don't remove duplication 

O

[...array1,...array2] //   =>  don't remove duplication 

O

[...new Set([...array1 ,...array2])]; //   => remove duplication

86
2017-08-14 08:08



Aquí hay una versión ligeramente diferente del ciclo. Con algunas de las optimizaciones en la última versión de Chrome, es el método más rápido para resolver la unión de las dos matrices (Chrome 38.0.2111).

http://jsperf.com/merge-two-arrays-keeping-only-unique-values

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [];

var arr = array1.concat(array2),
  len = arr.length;

while (len--) {
  var itm = arr[len];
  if (array3.indexOf(itm) === -1) {
    array3.unshift(itm);
  }
}

while loop: ~ 589k ops / s
filtro: ~ 445k ops / s
lodash: 308k ops / s
para bucles: 225k ops / s

Un comentario señaló que una de mis variables de configuración causaba que mi ciclo se adelantara al resto, porque no tenía que inicializar una matriz vacía para escribir. Estoy de acuerdo con eso, así que reescribí la prueba para igualar el campo de juego, e incluí una opción incluso más rápida.

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/21

var whileLoopAlt = function(array1, array2) {
    var array3 = [];
    var arr = array1.concat(array2);
    var len = arr.length;
    var assoc = {};

    while(len--) {
        var itm = arr[len];

        if(!assoc[itm]) { // Eliminate the indexOf call
            array3.unshift(itm);
            assoc[itm] = true;
        }
    }

    return array3;
};

En esta solución alternativa, he combinado una solución de matriz asociativa de una respuesta para eliminar el .indexOf() llamada en el bucle que estaba ralentizando mucho las cosas con un segundo ciclo, e incluía algunas de las otras optimizaciones que otros usuarios han sugerido en sus respuestas también.

La respuesta principal aquí con el doble bucle en cada valor (i-1) es todavía significativamente más lenta. Lodash sigue siendo fuerte, y todavía lo recomendaría a cualquiera que no le importe agregar una biblioteca a su proyecto. Para aquellos que no quieran, mi ciclo while sigue siendo una buena respuesta y la respuesta del filtro tiene una muy buena muestra aquí, superando todas mis pruebas con el último Canary Chrome (44.0.2360) al momento de escribir esto.

Revisa La respuesta de Mike y La respuesta de Dan Stocker si quieres subirlo un peldaño en velocidad. Esos son, con mucho, los más rápidos de todos los resultados después de pasar por casi todas las respuestas viables.


30
2017-08-04 14:14



Usando un Conjunto (ECMAScript 2015), será tan simple como eso:

const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = Array.from(new Set(array1.concat(array2)));

27
2018-01-06 19:05



Puedes hacerlo simplemente con ECMAScript 6,

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
  • Utilizar el operador de propagación para concatenar la matriz.
  • Utilizar Conjunto para crear un conjunto distinto de elementos.
  • Nuevamente use el operador de propagación para convertir el conjunto en una matriz.

26
2018-04-07 07:26