¿Hay alguna manera de devolver la diferencia entre dos matrices en JavaScript?
Por ejemplo:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
fuente
¿Hay alguna manera de devolver la diferencia entre dos matrices en JavaScript?
Por ejemplo:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
Supongo que está comparando una matriz normal. De lo contrario, debe cambiar el bucle for por un bucle for .. in .
function arr_diff (a1, a2) {
var a = [], diff = [];
for (var i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (var i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
for (var k in a) {
diff.push(k);
}
return diff;
}
console.log(arr_diff(['a', 'b'], ['a', 'b', 'c', 'd']));
console.log(arr_diff("abcd", "abcde"));
console.log(arr_diff("zxc", "zxc"));
Una solución mejor, si no le importa la compatibilidad con versiones anteriores, es usar el filtro. Pero aún así, esta solución funciona.
var a1 = ['a', 'b'];
y var a2 = ['a', 'b', 'c', 'd', 'b'];
, devolverá una respuesta incorrecta , es decir, en ['c', 'd', 'b']
lugar de ['c', 'd']
.
function diff2(a, b) { var i, la = a.length, lb = b.length, res = []; if (!la) return b; else if (!lb) return a; for (i = 0; i < la; i++) { if (b.indexOf(a[i]) === -1) res.push(a[i]); } for (i = 0; i < lb; i++) { if (a.indexOf(b[i]) === -1) res.push(b[i]); } return res; }
Hay una mejor manera de usar ES7:
Intersección
let intersection = arr1.filter(x => arr2.includes(x));
Porque [1,2,3] [2,3]
rendirá [2,3]
. Por otro lado, for [1,2,3] [2,3,5]
devolverá lo mismo.
Diferencia
let difference = arr1.filter(x => !arr2.includes(x));
Porque [1,2,3] [2,3]
rendirá [1]
. Por otro lado, for [1,2,3] [2,3,5]
devolverá lo mismo.
Para una diferencia simétrica , puedes hacer:
let difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
De esta manera, obtendrá una matriz que contiene todos los elementos de arr1 que no están en arr2 y viceversa.
Como @Joshaven Potter señaló en su respuesta, puede agregar esto a Array.prototype para que pueda usarse así:
Array.prototype.diff = function(arr2) { return this.filter(x => !arr2.includes(x)); }
[1, 2, 3].diff([2, 3])
< 0
lugar de== -1
Array
diferencia se llama así set operation
, porque la búsqueda de propiedades es el trabajo propio de Set
s, que son órdenes de magnitud más rápido que indexOf
/ includes
. En pocas palabras, su solución es muy ineficiente y bastante lenta.
Set
, los valores tienen que ser únicos, ¿no?
[1,2,3] [2,3,5]
dado que los números son únicos, pero si lo dijera [1,1,2,3] [1,2,3,5]
y esperara, [1]
no podría usarlo Set
. Sin embargo, su solución tampoco funcionaría: - / Terminé creando esta función porque no pude encontrar una manera satisfactoria de hacerlo de manera más sucinta. Si tienes alguna idea sobre cómo hacerlo, ¡me encantaría saberlo!
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
////////////////////
// Examples
////////////////////
[1,2,3,4,5,6].diff( [3,4,5] );
// => [1, 2, 6]
["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);
// => ["test5", "test6"]
Nota indexOf y filter no están disponibles en ie antes de ie9.
[1,2,3].diff([3,4,5])
volverá en [1,2]
lugar de [1,2,4,5]
hacerlo, por lo que no resuelve el problema en la pregunta original, algo a tener en cuenta.
Esta es, con mucho, la forma más fácil de obtener exactamente el resultado que está buscando, utilizando jQuery:
var diff = $(old_array).not(new_array).get();
diff
ahora contiene lo que estaba en old_array
eso no está ennew_array
{a: 1} != {a: 1}
) ( prueba )
.not
con una matriz, jQuery usa su utilidad incorporada.grep()
que es específicamente para filtrar matrices. No puedo ver esto cambiando.
El método de diferencia en Underscore (o su reemplazo directo , Lo-Dash ) también puede hacer esto:
(R)eturns the values from array that are not present in the other arrays
_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]
Al igual que con cualquier función de subrayado, también puede usarla en un estilo más orientado a objetos:
_([1, 2, 3, 4, 5]).difference([5, 2, 10]);
Hay dos posibles interpretaciones para la "diferencia". Te dejaré elegir cuál quieres. Digamos que tienes:
var a1 = ['a', 'b' ];
var a2 = [ 'b', 'c'];
Si desea obtener ['a']
, use esta función:
function difference(a1, a2) {
var result = [];
for (var i = 0; i < a1.length; i++) {
if (a2.indexOf(a1[i]) === -1) {
result.push(a1[i]);
}
}
return result;
}
Si desea obtener ['a', 'c']
(todos los elementos contenidos en uno a1
o a2
, pero no en ambos, la llamada diferencia simétrica ), use esta función:
function symmetricDifference(a1, a2) {
var result = [];
for (var i = 0; i < a1.length; i++) {
if (a2.indexOf(a1[i]) === -1) {
result.push(a1[i]);
}
}
for (i = 0; i < a2.length; i++) {
if (a1.indexOf(a2[i]) === -1) {
result.push(a2[i]);
}
}
return result;
}
Si está usando lodash, puede usar _.difference(a1, a2)
(caso 1 arriba) o _.xor(a1, a2)
(caso 2).
Si está utilizando Underscore.js, puede usar el _.difference(a1, a2)
función para el caso 1.
El código anterior funciona en todos los navegadores. Sin embargo, para matrices grandes de más de aproximadamente 10,000 artículos, se vuelve bastante lento, porque tiene una complejidad O (n²). En muchos navegadores modernos, podemos aprovechar el Set
objeto ES6 para acelerar las cosas. Lodash usa automáticamente Set
cuando está disponible. Si no está usando lodash, use la siguiente implementación, inspirada en la publicación de blog de Axel Rauschmayer :
function difference(a1, a2) {
var a2Set = new Set(a2);
return a1.filter(function(x) { return !a2Set.has(x); });
}
function symmetricDifference(a1, a2) {
return difference(a1, a2).concat(difference(a2, a1));
}
El comportamiento de todos los ejemplos puede ser sorprendente o no obvio si le interesan los conjuntos -0, +0, NaN o dispersos. (Para la mayoría de los usos, esto no importa).
Para obtener la diferencia simétrica , debe comparar las matrices de ambas maneras (o de todas las formas en caso de múltiples matrices)
// diff between just two arrays:
function arrayDiff(a, b) {
return [
...a.filter(x => !b.includes(x)),
...b.filter(x => !a.includes(x))
];
}
// diff between multiple arrays:
function arrayDiff(...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter(x => !unique.includes(x));
}));
}
// diff between just two arrays:
function arrayDiff(a, b) {
return [
...a.filter(x => b.indexOf(x) === -1),
...b.filter(x => a.indexOf(x) === -1)
];
}
// diff between multiple arrays:
function arrayDiff(...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter(x => unique.indexOf(x) === -1);
}));
}
// diff between just two arrays:
function arrayDiff(a, b) {
var arrays = Array.prototype.slice.call(arguments);
var diff = [];
arrays.forEach(function(arr, i) {
var other = i === 1 ? a : b;
arr.forEach(function(x) {
if (other.indexOf(x) === -1) {
diff.push(x);
}
});
})
return diff;
}
// diff between multiple arrays:
function arrayDiff() {
var arrays = Array.prototype.slice.call(arguments);
var diff = [];
arrays.forEach(function(arr, i) {
var others = arrays.slice(0);
others.splice(i, 1);
var otherValues = Array.prototype.concat.apply([], others);
var unique = otherValues.filter(function (x, j) {
return otherValues.indexOf(x) === j;
});
diff = diff.concat(arr.filter(x => unique.indexOf(x) === -1));
});
return diff;
}
Ejemplo:
// diff between two arrays:
const a = ['a', 'd', 'e'];
const b = ['a', 'b', 'c', 'd'];
arrayDiff(a, b); // (3) ["e", "b", "c"]
// diff between multiple arrays
const a = ['b', 'c', 'd', 'e', 'g'];
const b = ['a', 'b'];
const c = ['a', 'e', 'f'];
arrayDiff(a, b, c); // (4) ["c", "d", "g", "f"]
function arrayDiffByKey(key, ...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter( x =>
!unique.some(y => x[key] === y[key])
);
}));
}
Ejemplo:
const a = [{k:1}, {k:2}, {k:3}];
const b = [{k:1}, {k:4}, {k:5}, {k:6}];
const c = [{k:3}, {k:5}, {k:7}];
arrayDiffByKey('k', a, b, c); // (4) [{k:2}, {k:4}, {k:6}, {k:7}]
Un enfoque más limpio en ES6 es la siguiente solución.
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
a2.filter(d => !a1.includes(d)) // gives ["c", "d"]
a2.filter(d => a1.includes(d)) // gives ["a", "b"]
[ ...a2.filter(d => !a1.includes(d)),
...a1.filter(d => !a2.includes(d)) ]
a1 = ['a', 'b', 'e']
: e no se extraerá.
Podrías usar un Set en este caso. Está optimizado para este tipo de operación (unión, intersección, diferencia).
Asegúrese de que se aplique a su caso, una vez que no permita duplicados.
var a = new JS.Set([1,2,3,4,5,6,7,8,9]);
var b = new JS.Set([2,4,6,8]);
a.difference(b)
// -> Set{1,3,5,7,9}
Set
función sin tener que conseguir todo lo demás ...
function diff(a1, a2) {
return a1.concat(a2).filter(function(val, index, arr){
return arr.indexOf(val) === arr.lastIndexOf(val);
});
}
Combine ambas matrices, los valores únicos aparecerán solo una vez, por lo que indexOf () será el mismo que lastIndexOf ().
para restar una matriz de otra, simplemente use el fragmento a continuación:
var a1 = ['1','2','3','4','6'];
var a2 = ['3','4','5'];
var items = new Array();
items = jQuery.grep(a1,function (item) {
return jQuery.inArray(item, a2) < 0;
});
Devolverá ['1,' 2 ',' 6 '] que son elementos de la primera matriz que no existen en la segunda.
Por lo tanto, de acuerdo con su ejemplo de problema, el siguiente código es la solución exacta:
var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];
var _array = new Array();
_array = jQuery.grep(array2, function (item) {
return jQuery.inArray(item, array1) < 0;
});
Con la llegada de ES6 con sets y operador splat (al momento de funcionar solo en Firefox, consulte la tabla de compatibilidad ), puede escribir el siguiente delineador:
var a = ['a', 'b', 'c', 'd'];
var b = ['a', 'b'];
var b1 = new Set(b);
var difference = [...new Set([...a].filter(x => !b1.has(x)))];
que dará lugar a [ "c", "d" ]
.
b.filter(x => !a.indexOf(x)))
O(n + m)
su solución es O(n * m)
donde nym son longitudes de matrices. Tome listas largas y mi solución se ejecutará en segundos, mientras que la suya tomará horas.
a.filter(x => !b1.has(x))
es más simple Y tenga en cuenta la especificación sólo requiere la complejidad de ser n * f(m) + m
con f(m)
sublinear en promedio. Es mejor que n * m
, pero no necesariamente n + m
.
var difference = [...new Set([...a].filter(x => !b1.has(x)))];
¿ Por qué estás creando una matriz 'a' duplicada? ¿Por qué está convirtiendo el resultado del filtro en un conjunto y luego nuevamente en una matriz? ¿No es esto equivalente avar difference = a.filter(x => !b1.has(x));
Calcular difference
entre dos matrices es una de las Set
operaciones. El término ya indica que se Set
debe usar el tipo nativo para aumentar la velocidad de búsqueda. De todos modos, hay tres permutaciones cuando calcula la diferencia entre dos conjuntos:
[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]
Aquí hay una solución funcional que refleja estas permutaciones.
difference
:// small, reusable auxiliary functions
const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// left difference
const differencel = xs => ys => {
const zs = createSet(ys);
return filter(x => zs.has(x)
? false
: true
) (xs);
};
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
// run the computation
console.log( differencel(xs) (ys) );
difference
:differencer
es trivial Es solo differencel
con argumentos invertidos. Puede escribir una función por conveniencia:const differencer = flip(differencel)
. ¡Eso es todo!
difference
:Ahora que tenemos el izquierdo y el derecho, implementar la simétrica también difference
es trivial:
// small, reusable auxiliary functions
const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const concat = y => xs => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// left difference
const differencel = xs => ys => {
const zs = createSet(ys);
return filter(x => zs.has(x)
? false
: true
) (xs);
};
// symmetric difference
const difference = ys => xs =>
concat(differencel(xs) (ys)) (flip(differencel) (xs) (ys));
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
// run the computation
console.log( difference(xs) (ys) );
Supongo que este ejemplo es un buen punto de partida para obtener una impresión de lo que significa la programación funcional:
Programación con bloques de construcción que se pueden conectar de muchas maneras diferentes.
Una solución usando indexOf()
estará bien para matrices pequeñas pero a medida que crecen en longitud, el rendimiento del algoritmo se acerca O(n^2)
. Aquí hay una solución que funcionará mejor para matrices muy grandes mediante el uso de objetos como matrices asociativas para almacenar las entradas de la matriz como claves; también elimina entradas duplicadas automáticamente, pero solo funciona con valores de cadena (o valores que se pueden almacenar de forma segura como cadenas):
function arrayDiff(a1, a2) {
var o1={}, o2={}, diff=[], i, len, k;
for (i=0, len=a1.length; i<len; i++) { o1[a1[i]] = true; }
for (i=0, len=a2.length; i<len; i++) { o2[a2[i]] = true; }
for (k in o1) { if (!(k in o2)) { diff.push(k); } }
for (k in o2) { if (!(k in o1)) { diff.push(k); } }
return diff;
}
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
arrayDiff(a1, a2); // => ['c', 'd']
arrayDiff(a2, a1); // => ['c', 'd']
La respuesta anterior de Joshaven Potter es genial. Pero devuelve elementos en la matriz B que no están en la matriz C, pero no al revés. Por ejemplo, si var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
entonces generará: ==> [1,2,6]
, pero no [1,2,6,7]
, que es la diferencia real entre los dos. Todavía puede usar el código de Potter anterior, pero simplemente vuelva a hacer la comparación una vez al revés también:
Array.prototype.diff = function(a) {
return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};
////////////////////
// Examples
////////////////////
var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
var b=[3,4,5,7].diff([1,2,3,4,5,6]);
var c=a.concat(b);
console.log(c);
Esto debería generar: [ 1, 2, 6, 7 ]
Otra forma de resolver el problema.
function diffArray(arr1, arr2) {
return arr1.concat(arr2).filter(function (val) {
if (!(arr1.includes(val) && arr2.includes(val)))
return val;
});
}
diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]); // return [7, 4, 5]
Además, puede usar la sintaxis de la función de flecha:
const diffArray = (arr1, arr2) => arr1.concat(arr2)
.filter(val => !(arr1.includes(val) && arr2.includes(val)));
diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]); // return [7, 4, 5]
Array.prototype.difference = function(e) {
return this.filter(function(i) {return e.indexOf(i) < 0;});
};
eg:-
[1,2,3,4,5,6,7].difference( [3,4,5] );
=> [1, 2, 6 , 7]
difference
como función en una versión futura y esta función tiene una firma de función diferente a la suya, romperá su código o las bibliotecas extranjeras que usen esta función.
Solución muy simple con la función de filtro de JavaScript:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
function diffArray(arr1, arr2) {
var newArr = [];
var myArr = arr1.concat(arr2);
newArr = myArr.filter(function(item){
return arr2.indexOf(item) < 0 || arr1.indexOf(item) < 0;
});
alert(newArr);
}
diffArray(a1, a2);
Qué tal esto:
Array.prototype.contains = function(needle){
for (var i=0; i<this.length; i++)
if (this[i] == needle) return true;
return false;
}
Array.prototype.diff = function(compare) {
return this.filter(function(elem) {return !compare.contains(elem);})
}
var a = new Array(1,4,7, 9);
var b = new Array(4, 8, 7);
alert(a.diff(b));
Entonces, de esta manera, puede hacer array1.diff(array2)
para obtener su diferencia (Sin embargo, la complejidad de tiempo horrible para el algoritmo - O (array1.length x array2.length) creo)
Usando http://phrogz.net/JS/ArraySetMath.js puedes:
var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];
var array3 = array2.subtract( array1 );
// ["test5", "test6"]
var array4 = array1.exclusion( array2 );
// ["test5", "test6"]
function diffArray(arr1, arr2) {
var newArr = arr1.concat(arr2);
return newArr.filter(function(i){
return newArr.indexOf(i) == newArr.lastIndexOf(i);
});
}
esto funciona para mi
filter
)fn
Parámetro de devolución de llamada opcional que le permite especificar cómo comparar elementos de la matrizfunction diff(a, b, fn){
var max = Math.max(a.length, b.length);
d = [];
fn = typeof fn === 'function' ? fn : false
for(var i=0; i < max; i++){
var ac = i < a.length ? a[i] : undefined
bc = i < b.length ? b[i] : undefined;
for(var k=0; k < max; k++){
ac = ac === undefined || (k < b.length && (fn ? fn(ac, b[k]) : ac == b[k])) ? undefined : ac;
bc = bc === undefined || (k < a.length && (fn ? fn(bc, a[k]) : bc == a[k])) ? undefined : bc;
if(ac == undefined && bc == undefined) break;
}
ac !== undefined && d.push(ac);
bc !== undefined && d.push(bc);
}
return d;
}
alert(
"Test 1: " +
diff(
[1, 2, 3, 4],
[1, 4, 5, 6, 7]
).join(', ') +
"\nTest 2: " +
diff(
[{id:'a',toString:function(){return this.id}},{id:'b',toString:function(){return this.id}},{id:'c',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
[{id:'a',toString:function(){return this.id}},{id:'e',toString:function(){return this.id}},{id:'f',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
function(a, b){ return a.id == b.id; }
).join(', ')
);
length
valores. Ya es una propiedad simple. jsperf.com/array-length-caching
Esto está funcionando: básicamente combina las dos matrices, busca los duplicados y empuja lo que no está duplicado en una nueva matriz, que es la diferencia.
function diff(arr1, arr2) {
var newArr = [];
var arr = arr1.concat(arr2);
for (var i in arr){
var f = arr[i];
var t = 0;
for (j=0; j<arr.length; j++){
if(arr[j] === f){
t++;
}
}
if (t === 1){
newArr.push(f);
}
}
return newArr;
}
// enfoque es6
function diff(a, b) {
var u = a.slice(); //dup the array
b.map(e => {
if (u.indexOf(e) > -1) delete u[u.indexOf(e)]
else u.push(e) //add non existing item to temp array
})
return u.filter((x) => {return (x != null)}) //flatten result
}
Complejidad simétrica y lineal . Requiere ES6.
function arrDiff(arr1, arr2) {
var arrays = [arr1, arr2].sort((a, b) => a.length - b.length);
var smallSet = new Set(arrays[0]);
return arrays[1].filter(x => !smallSet.has(x));
}
Otra respuesta más, pero parece que nadie mencionó jsperf donde comparan varios algoritmos y soporte tecnológico: https://jsperf.com/array-difference-javascript parece que usar el filtro obtiene los mejores resultados. Gracias
Solo pensando ... en aras de un desafío ;-) ¿funcionaría esto ... (para matrices básicas de cadenas, números, etc.) sin matrices anidadas
function diffArrays(arr1, arr2, returnUnion){
var ret = [];
var test = {};
var bigArray, smallArray, key;
if(arr1.length >= arr2.length){
bigArray = arr1;
smallArray = arr2;
} else {
bigArray = arr2;
smallArray = arr1;
}
for(var i=0;i<bigArray.length;i++){
key = bigArray[i];
test[key] = true;
}
if(!returnUnion){
//diffing
for(var i=0;i<smallArray.length;i++){
key = smallArray[i];
if(!test[key]){
test[key] = null;
}
}
} else {
//union
for(var i=0;i<smallArray.length;i++){
key = smallArray[i];
if(!test[key]){
test[key] = true;
}
}
}
for(var i in test){
ret.push(i);
}
return ret;
}
array1 = "test1", "test2","test3", "test4", "test7"
array2 = "test1", "test2","test3","test4", "test5", "test6"
diffArray = diffArrays(array1, array2);
//returns ["test5","test6","test7"]
diffArray = diffArrays(array1, array2, true);
//returns ["test1", "test2","test3","test4", "test5", "test6","test7"]
Tenga en cuenta que la clasificación probablemente no será como se indicó anteriormente ... pero si lo desea, llame a .sort () en la matriz para ordenarlo.
Quería una función similar que tomara una matriz antigua y una matriz nueva y me diera una matriz de elementos agregados y una matriz de elementos eliminados, y quería que fuera eficiente (¡así que no contiene!).
Puedes jugar con mi solución propuesta aquí: http://jsbin.com/osewu3/12 .
¿Alguien puede ver algún problema / mejora de ese algoritmo? ¡Gracias!
Listado de código:
function diff(o, n) {
// deal with empty lists
if (o == undefined) o = [];
if (n == undefined) n = [];
// sort both arrays (or this won't work)
o.sort(); n.sort();
// don't compare if either list is empty
if (o.length == 0 || n.length == 0) return {added: n, removed: o};
// declare temporary variables
var op = 0; var np = 0;
var a = []; var r = [];
// compare arrays and add to add or remove lists
while (op < o.length && np < n.length) {
if (o[op] < n[np]) {
// push to diff?
r.push(o[op]);
op++;
}
else if (o[op] > n[np]) {
// push to diff?
a.push(n[np]);
np++;
}
else {
op++;np++;
}
}
// add remaining items
if( np < n.length )
a = a.concat(n.slice(np, n.length));
if( op < o.length )
r = r.concat(o.slice(op, o.length));
return {added: a, removed: r};
}
Estaba buscando una respuesta simple que no implicara el uso de diferentes bibliotecas, y se me ocurrió una propia que no creo que se haya mencionado aquí. No sé qué tan eficiente es ni nada, pero funciona;
function find_diff(arr1, arr2) {
diff = [];
joined = arr1.concat(arr2);
for( i = 0; i <= joined.length; i++ ) {
current = joined[i];
if( joined.indexOf(current) == joined.lastIndexOf(current) ) {
diff.push(current);
}
}
return diff;
}
Para mi código, también necesito sacar duplicados, pero supongo que no siempre es preferible.
Supongo que el principal inconveniente es que potencialmente está comparando muchas opciones que ya han sido rechazadas.
littlebit arregla la mejor respuesta
function arr_diff(a1, a2)
{
var a=[], diff=[];
for(var i=0;i<a1.length;i++)
a[a1[i]]=a1[i];
for(var i=0;i<a2.length;i++)
if(a[a2[i]]) delete a[a2[i]];
else a[a2[i]]=a2[i];
for(var k in a)
diff.push(a[k]);
return diff;
}
Esto tendrá en cuenta el tipo de elemento actual. b / c cuando hacemos un [a1 [i]] convierte un valor a cadena desde su valor original, por lo que perdimos el valor real.
O(a1.length x log(a2.length))
: ¿es posible este rendimiento en JavaScript?