Ich habe zwei Ergebnissätze wie folgt:
// Result 1
[
{ 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" }
]
// Result 2
[
{ 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"}
]
Das Endergebnis, das ich brauche, ist der Unterschied zwischen diesen Arrays.
[{ value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan" }]
Kann man so etwas in JavaScript machen?
Wenn Sie nur native JS verwenden, wird so etwas funktionieren:
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"}]
function comparer(otherArray){
return function(current){
return otherArray.filter(function(other){
return other.value == current.value && other.display == current.display
}).length == 0;
}
}
var onlyInA = a.filter(comparer(b));
var onlyInB = b.filter(comparer(a));
result = onlyInA.concat(onlyInB);
console.log(result);
Sie könnten Array.prototype.filter()
in Kombination mit Array.prototype.some()
verwenden.
Hier ein Beispiel (vorausgesetzt, Ihre Arrays werden in den Variablen result1
und result2
gespeichert):
//Find values that are in result1 but not in result2
var uniqueResultOne = result1.filter(function(obj) {
return !result2.some(function(obj2) {
return obj.value == obj2.value;
});
});
//Find values that are in result2 but not in result1
var uniqueResultTwo = result2.filter(function(obj) {
return !result1.some(function(obj2) {
return obj.value == obj2.value;
});
});
//Combine the two arrays of unique entries
var result = uniqueResultOne.concat(uniqueResultTwo);
Ich gehe etwas allgemeiner vor, wenn auch in den Ideen den Ansätzen von @Cerbrus und @Kasper Moerch. Ich erstelle eine Funktion, die ein Prädikat akzeptiert, um zu bestimmen, ob zwei Objekte gleich sind (hier ignorieren wir die $$hashKey
-Eigenschaft, es könnte jedoch alles sein) und gibt 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 geringfügigen Vorteil gegenüber Cerebrus 'Ansatz (wie auch Kasper Moerch' Ansatz), da es frühzeitig entkommt. Wenn es eine Übereinstimmung findet, stört es den Rest der Liste nicht. Wenn ich eine curry
-Funktion zur Verfügung hätte, würde ich dies etwas anders machen, aber das funktioniert gut.
In einem Kommentar wurde nach einer detaillierteren Erklärung für Anfänger gefragt. 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 true
oder false
zurückgeben, kann sie als "Prädikatfunktion" bezeichnet werden. Dies ist jedoch nur eine Terminologie. Der Hauptpunkt ist, dass makeSymmDiffFunc
mit einer Funktion konfiguriert ist, die zwei Objekte akzeptiert und true
zurückgibt, wenn wir sie als gleich betrachten, false
, wenn wir dies nicht tun.
makeSymmDiffFunc
(read "make symmetric difference function") gibt uns eine neue Funktion zurück:
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 es 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 es noch einmal anschaue, hätte ich definitiv einen Hinweis aus Ihrem Code nehmen und die Hauptfunktion mit some
ein wenig vereinfachen können:
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));
};
};
}());
complement
verwendet das Prädikat und gibt die Elemente der ersten Liste nicht in der zweiten zurück. Dies ist einfacher als mein erster Durchlauf mit einer separaten contains
-Funktion.
Schließlich wird die Hauptfunktion in einen sofort aufgerufenen Funktionsausdruck (IIFE) eingeschlossen, um die interne complement
-Funktion außerhalb des globalen Bereichs zu halten.
Update, einige Jahre später
Nun, da ES2015 mittlerweile allgegenwärtig ist, würde ich dieselbe 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"}
import differenceBy from 'lodash/differenceBy'
const myDifferences = differenceBy(Result1, Result2, 'value')
Dadurch wird der Unterschied zwischen zwei Arrays von Objekten mit der Taste value
zum Vergleich zurückgegeben. Beachten Sie, dass zwei Dinge mit demselben Wert nicht zurückgegeben werden, da die anderen Schlüssel ignoriert werden.
Dies ist ein Teil von lodash .
Sie können ein Objekt mit Schlüsseln als eindeutigen Wert für jedes Objekt im Array erstellen und dann jedes Array anhand des Vorhandenseins des Schlüssels im Objekt des anderen filtern. Es reduziert die Komplexität der Operation.
ES6
let 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"}];
let 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"}];
let valuesA = a.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let valuesB = b.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let result = [...a.filter(({value}) => !valuesB[value]), ...b.filter(({value}) => !valuesA[value])];
console.log(result);
ES5
var 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"}];
var 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 valuesA = a.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var valuesB = b.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var result = a.filter(function(c){ return !valuesB[c.value]}).concat(b.filter(function(c){ return !valuesA[c.value]}));
console.log(result);
Ich denke, dass die @ Cerbrus-Lösung genau richtig ist. Ich habe die gleiche Lösung implementiert, aber den wiederholten Code in seine eigene Funktion (DRY) extrahiert.
function filterByDifference(array1, array2, compareField) {
var onlyInA = differenceInFirstArray(array1, array2, compareField);
var onlyInb = differenceInFirstArray(array2, array1, compareField);
return onlyInA.concat(onlyInb);
}
function differenceInFirstArray(array1, array2, compareField) {
return array1.filter(function (current) {
return array2.filter(function (current_b) {
return current_b[compareField] === current[compareField];
}).length == 0;
});
}
Für diejenigen, die One-Liner-Lösungen in ES6 mögen:
const arrayOne = [
{ 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" },
];
const arrayTwo = [
{ 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"},
];
const results = arrayOne.filter(({ value: id1 }) => !arrayTwo.some(({ value: id2 }) => id2 === id1));
console.log(results);
Ich habe diese Lösung mit Filter und einigen gefunden.
resultFilter = (firstArray, secondArray) => {
return firstArray.filter(firstArrayItem =>
!secondArray.some(
secondArrayItem => firstArrayItem._user === secondArrayItem._user
)
);
};
Die meisten Antworten sind ziemlich komplex, aber ist die Logik dahinter nicht einfach?
const getArraysDifference = (longerArray, array2) => {
const difference = [];
longerArray.forEach(el1 => { /*1*/
el1IsPresentInArr2 = array2.some(el2 => el2.value === el1.value); /*2*/
if (!el1IsPresentInArr2) { /*3*/
difference.Push(el1); /*4*/
}
});
return difference;
}
O (n ^ 2) -Komplexität.
Ich habe ein verallgemeinertes Diff erstellt, das 2 Objekte jeder Art vergleicht und einen Modifikations-Handler ausführen kann Gist.github.com/bortunac "diff.js" ein Ex der Verwendung von:
old_obj={a:1,b:2,c:[1,2]}
now_obj={a:2 , c:[1,3,5],d:55}
die Eigenschaft a wird geändert, b wird gelöscht, c wird geändert, d wird hinzugefügt
var handler=function(type,pointer){
console.log(type,pointer,this.old.point(pointer)," | ",this.now.point(pointer));
}
verwenden Sie jetzt wie
df=new diff();
df.analize(now_obj,old_obj);
df.react(handler);
die Konsole wird angezeigt
mdf ["a"] 1 | 2
mdf ["c", "1"] 2 | 3
add ["c", "2"] undefined | 5
add ["d"] undefined | 55
del ["b"] 2 | undefined