Adopto un enfoque un poco más de propósito general, aunque similar en ideas a los enfoques de @Cerbrus y @Kasper Moerch . Creo una función que acepta un predicado para determinar si dos objetos son iguales (aquí ignoramos la $$hashKeypropiedad, pero podría ser cualquier cosa) y devuelvo una función que calcula la diferencia simétrica de dos listas basadas en ese predicado:
a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]
var makeSymmDiffFunc = (function() {
var contains = function(pred, a, list) {
var idx = -1, len = list.length;
while (++idx < len) {if (pred(a, list[idx])) {return true;}}
return false;
};
var complement = function(pred, a, b) {
return a.filter(function(elem) {return !contains(pred, elem, b);});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
var myDiff = makeSymmDiffFunc(function(x, y) {
return x.value === y.value && x.display === y.display;
});
var result = myDiff(a, b); //=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}
Tiene una pequeña ventaja sobre el enfoque de Cerebrus (al igual que el enfoque de Kasper Moerch) en que se escapa temprano; si encuentra una coincidencia, no se molesta en comprobar el resto de la lista. Si tuviera una curryfunción a mano, haría esto de manera un poco diferente, pero funciona bien.
Explicación
Un comentario pidió una explicación más detallada para principiantes. He aquí un intento.
Pasamos la siguiente función a makeSymmDiffFunc:
function(x, y) {
return x.value === y.value && x.display === y.display;
}
Esta función es la forma en que decidimos que dos objetos son iguales. Como todas las funciones que devuelven trueo false, se puede llamar una "función de predicado", pero eso es solo terminología. El punto principal es que makeSymmDiffFuncestá configurado con una función que acepta dos objetos y devuelve truesi los consideramos iguales, falsesi no.
Usando eso, makeSymmDiffFunc(lea "hacer una función de diferencia simétrica") nos devuelve una nueva función:
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
Esta es la función que realmente usaremos. Le pasamos dos listas y encuentra los elementos en la primera no en la segunda, luego los de la segunda no en la primera y combina estas dos listas.
Sin embargo, volviendo a mirarlo, definitivamente podría haber tomado una pista de su código y simplificar un poco la función principal usando some:
var makeSymmDiffFunc = (function() {
var complement = function(pred, a, b) {
return a.filter(function(x) {
return !b.some(function(y) {return pred(x, y);});
});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
complementusa el predicado y devuelve los elementos de su primera lista, no de la segunda. Esto es más simple que mi primer paso con una containsfunción separada .
Finalmente, la función principal está envuelta en una expresión de función invocada inmediatamente ( IIFE ) para mantener la complementfunción interna fuera del alcance global.
Actualización, unos años después
Ahora que ES2015 se ha vuelto bastante ubicuo, sugeriría la misma técnica, con mucho menos repetición:
const diffBy = (pred) => (a, b) => a.filter(x => !b.some(y => pred(x, y)))
const makeSymmDiffFunc = (pred) => (a, b) => diffBy(pred)(a, b).concat(diffBy(pred)(b, a))
const myDiff = makeSymmDiffFunc((x, y) => x.value === y.value && x.display === y.display)
const result = myDiff(a, b)
//=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}