Ich möchte zwei Arrays vergleichen ... idealerweise effizient. Nichts Besonderes, nur true
wenn sie identisch sind und false
wenn nicht. Es überrascht nicht, dass der Vergleichsoperator nicht zu funktionieren scheint.
var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2); // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2)); // Returns true
JSON-Codierung für jedes Array funktioniert, aber gibt es eine schnellere oder "bessere" Möglichkeit, Arrays einfach zu vergleichen, ohne jeden Wert durchlaufen zu müssen?
Um Arrays zu vergleichen, durchlaufen Sie sie und vergleichen Sie jeden Wert:
// Warn if overriding existing method
if(Array.prototype.equals)
console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});
[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;
Sie können sagen " Aber es ist viel schneller, Strings zu vergleichen - keine Schleifen ... " Nun, dann sollten Sie beachten, dass es ARE-Schleifen gibt. Erste rekursive Schleife, die Array in Zeichenfolge konvertiert, und zweite, die zwei Zeichenfolgen vergleicht. Diese Methode ist also schneller als die Verwendung von Zeichenfolgen .
Ich glaube, dass größere Datenmengen immer in Arrays gespeichert werden sollten, nicht in Objekten. Wenn Sie jedoch Objekte verwenden, können diese auch teilweise verglichen werden.
Hier ist wie:
Ich habe bereits erwähnt, dass zwei Objektinstanzen werden nie gleich sein, auch wenn sie dieselben Daten zur Zeit enthalten:
({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666}) //false
Dies hat einen Grund, da es beispielsweise private Variablen innerhalb von Objekten geben kann.
Wenn Sie jedoch nur die Objektstruktur verwenden, um Daten zu enthalten, ist ein Vergleich weiterhin möglich:
Object.prototype.equals = function(object2) {
//For the first loop, we only check for types
for (propName in this) {
//Check for inherited methods and properties - like .equals itself
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
//Return false if the return value is different
if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
return false;
}
//Check instance type
else if (typeof this[propName] != typeof object2[propName]) {
//Different types => not equal
return false;
}
}
//Now a deeper check using other objects property names
for(propName in object2) {
//We must check instances anyway, there may be a property that only exists in object2
//I wonder, if remembering the checked values from the first loop would be faster or not
if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
return false;
}
else if (typeof this[propName] != typeof object2[propName]) {
return false;
}
//If the property is inherited, do not check any more (it must be equa if both objects inherit it)
if(!this.hasOwnProperty(propName))
continue;
//Now the detail check and recursion
//This returns the script back to the array comparing
/**REQUIRES Array.equals**/
if (this[propName] instanceof Array && object2[propName] instanceof Array) {
// recurse into the nested arrays
if (!this[propName].equals(object2[propName]))
return false;
}
else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
// recurse into another objects
//console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
if (!this[propName].equals(object2[propName]))
return false;
}
//Normal value comparison for strings and numbers
else if(this[propName] != object2[propName]) {
return false;
}
}
//If everything passed, let's say YES
return true;
}
Denken Sie jedoch daran, dass dies dazu dient, JSON-ähnliche Daten zu vergleichen, nicht Klasseninstanzen und andere Dinge. Wenn Sie mehr komplizierte Objekte vergleichen möchten, schauen Sie sich diese Antwort und ihre überlange Funktion an .
Damit dies funktioniert Array.equals
, müssen Sie die ursprüngliche Funktion ein wenig bearbeiten:
...
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
/**REQUIRES OBJECT COMPARE**/
else if (this[i] instanceof Object && array[i] instanceof Object) {
// recurse into another objects
//console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
...
Ich habe ein kleines Testwerkzeug für beide Funktionen erstellt .
indexOf
undcontains
Samy Bencherif hat nützliche Funktionen für den Fall vorbereitet , dass Sie in verschachtelten Arrays nach einem bestimmten Objekt suchen. Diese finden Sie hier: https://jsfiddle.net/SamyBencherif/8352y6yw/
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen