Ich verfolge einen etwas allgemeineren Ansatz, obwohl die Ideen den Ansätzen von @Cerbrus und @Kasper Moerch ähnlich sind . Ich erstelle eine Funktion, die ein Prädikat akzeptiert, um festzustellen, ob zwei Objekte gleich sind (hier ignorieren wir die $$hashKeyEigenschaft, aber es kann alles sein) und gebe eine Funktion zurück, die die symmetrische Differenz zweier Listen basierend auf diesem Prädikat berechnet:
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"}
Es hat einen kleinen Vorteil gegenüber Cerebrus 'Ansatz (wie auch Kasper Moerchs Ansatz), da es früh entkommt; Wenn eine Übereinstimmung gefunden wird, wird der Rest der Liste nicht überprüft. Wenn ich eine curryFunktion zur Hand hätte, würde ich das etwas anders machen, aber das funktioniert gut.
Erläuterung
In einem Kommentar wurde um eine ausführlichere Erklärung für Anfänger gebeten. Hier ist ein Versuch.
Wir übergeben die folgende Funktion an makeSymmDiffFunc:
function(x, y) {
return x.value === y.value && x.display === y.display;
}
Mit dieser Funktion entscheiden wir, dass zwei Objekte gleich sind. Wie alle Funktionen, die trueoder zurückgeben false, kann es als "Prädikatfunktion" bezeichnet werden, aber das ist nur Terminologie. Der Hauptpunkt ist, dass makeSymmDiffFuncmit einer Funktion konfiguriert wird, die zwei Objekte akzeptiert und zurückgibt, truewenn wir sie als gleich betrachten, falsewenn wir dies nicht tun.
Wenn Sie dies verwenden makeSymmDiffFunc(lesen Sie "Symmetrische Differenzfunktion machen"), erhalten Sie eine neue Funktion:
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
Dies ist die Funktion, die wir tatsächlich verwenden werden. Wir übergeben ihm zwei Listen und es findet die Elemente in der ersten nicht in der zweiten, dann die in der zweiten nicht in der ersten und kombinieren diese beiden Listen.
Wenn ich noch einmal darüber nachdenke, hätte ich definitiv einen Hinweis auf Ihren Code nehmen und die Hauptfunktion ein wenig vereinfachen können, indem ich Folgendes verwendet habe 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));
};
};
}());
complementverwendet das Prädikat und gibt die Elemente der ersten Liste zurück, die nicht in der zweiten Liste enthalten sind. Dies ist einfacher als mein erster Durchgang mit einer separaten containsFunktion.
Schließlich wird die Hauptfunktion in einen sofort aufgerufenen Funktionsausdruck ( IIFE ) eingeschlossen, um die interne complementFunktion aus dem globalen Bereich herauszuhalten.
Update einige Jahre später
Jetzt, da ES2015 ziemlich allgegenwärtig geworden ist, würde ich die gleiche Technik mit viel weniger Boilerplate vorschlagen:
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"}