compare arrays (2D & above also)
I have developed this method which compares 2 (or more) arrays, and returns whatever you wish as result.
This is done by converting the arrays to strings then comparing them, then converting back the result. (could also be used for other stuff) instead of just doing deep iterations and recursions to do the same thing..
example:
var arr1 = [[8,0,3,0,0,7,0,9,0],[0,9,0,0,3,0,0,0,0],[0,0,0,0,0,0,4,0,6],[0,0,0,0,3开发者_运维问答,9,7,6,0],[9,6,0,5,0,7,0,8,1],[0,7,4,6,8,0,0,0,0],[5,0,1,0,0,0,0,0,0],[0,0,0,0,5,0,0,7,0],[0,6,0,7,0,0,1,0,8]];
var arr2 = [[8,7,3,0,0,7,0,9,0],[0,9,0,0,3,0,0,0,0],[0,0,0,0,0,0,4,0,6],[0,0,0,0,3,9,7,6,0],[9,6,0,5,0,7,0,8,1],[0,6,4,6,8,0,0,0,0],[5,0,1,0,0,0,0,0,0],[0,0,0,0,5,0,3,7,0],[1,6,0,7,0,0,1,0,8]];
arr1 = JSON.stringify( arr1 );
arr2 = JSON.stringify( arr2 );
var temp = ''; // this object will hold the XOR result
console.log( arr1 );
console.log( arr2 );
for( var i=0; i < arr1.length; i++ ){
if( arr1[i] == '[' || arr1[i] == ']' || arr1[i] == ',' )
temp += arr1[i];
else
temp += arr1[i] == arr2[i] ? 0 : 1;
}
console.log( temp );
what are your thoughts of this method? better for performance I believe.
Here's a version that works for any type of object:
var arr1 = [[8,0,3,0,0,7,0,9,0],[0,9,0,0,3,0,0,0,0],[0,0,0,0,0,0,4,0,6],[0,0,0,0,3,9,7,6,0],[9,6,0,5,0,7,0,8,1],[0,7,4,6,8,0,0,0,0],[5,0,1,0,0,0,0,0,0],[0,0,0,0,5,0,0,7,0],[0,6,0,7,0,0,1,0,8]];
var arr2 = [[8,0,3,0,0,7,0,9,0],[0,9,0,0,3,0,0,0,0],[0,0,0,0,0,0,4,0,6],[0,0,0,0,3,9,7,6,0],[9,6,0,5,0,7,0,8,1],[0,7,4,6,8,0,0,0,0],[5,0,1,0,0,0,0,0,0],[0,0,0,0,5,0,0,7,0],[0,6,0,7,0,0,1,0,8]];
alert(isEqual(arr1, arr2));
function isEqual(obj1, obj2) {
//make sure all keys are the same from obj1 -> obj2
for (var key in obj1) {
if (obj1[key] && ! obj2[key]) {
return false;
}
}
//make sure all keys are the same from obj2 -> obj1
for (var key in obj2) {
if (obj2[key] && ! obj1[key]) {
return false;
}
}
//make sure the key values themselves match
for (var key in obj1) {
var left = obj1[key];
var right = obj2[key];
if (left instanceof Function) {
//don't compare these
continue;
}
if (left instanceof Object || left instanceof Array){
if (! isEqual(left, right)) {
return false;
}
}
else if (left != right) {
return false;
}
}
return true;
}
Or if you want to list the locations of all the differences, you can use something like:
var arr1 = [[8,0,3,0,0,7,0,9,0],[0,9,0,0,3,0,0,0,0],[0,0,0,0,0,0,4,0,6],[0,0,0,0,3,9,7,6,0],[9,6,0,5,0,7,0,8,1],[0,7,4,6,8,0,0,0,0],[5,0,1,0,0,0,0,0,0],[0,0,0,0,5,0,0,7,0],[0,6,0,7,0,0,1,0,8]];
var arr2 = [[8,0,3,0,0,7,0,9,0],[0,9,0,0,3,0,0,0,0],[1,0,0,0,1,1,4,0,6],[0,0,0,0,3,9,7,6,0],[9,6,0,5,0,7,0,8,1],[0,7,4,6,8,0,0,0,0],[5,0,1,0,0,0,0,0,0],[0,0,0,0,5,0,0,7,0],[0,6,0,7,0,0,1,0,8]];
alert(listDifferences(arr1, arr2));
function listDifferences(obj1, obj2, deltaList, keyPath) {
if (! deltaList) {
deltaList = [];
keyPath = "";
}
//make sure all keys are the same from obj1 -> obj2
for (var key in obj1) {
if (obj1[key] && ! obj2[key]) {
deltaList.push("obj1" + keyPath + "[" + key + "]");
}
}
//make sure all keys are the same from obj2 -> obj1
for (var key in obj2) {
if (obj2[key] && ! obj1[key]) {
deltaList.push("obj2" + keyPath + "[" + key + "]");
}
}
//make sure the key values themselves match
for (var key in obj1) {
var left = obj1[key];
var right = obj2[key];
if (left instanceof Function) {
//don't compare these
continue;
}
if (left instanceof Object || left instanceof Array){
var startingLength = deltaList.length
if (listDifferences(left, right, deltaList, keyPath + "[" + key + "]").length > startingLength) {
deltaList.push("obj1" + keyPath + "[" + key + "]");
}
}
else if (left != right) {
deltaList.push("obj1" + keyPath + "[" + key + "]");
}
}
return deltaList;
}
I believe your method worsens performance at the expense of safety and readability. I strongly recommend against using this code in production unless:
- You know that your technique does in fact work in general, even for edge cases like comparing numbers with different digits (e.g.
10
and1
), or poorly-rounded numbers like8.999999998
. A test suite is in order. - You have proved through benchmarks, on a few different browsers, that this method is significantly faster than the recursive algorithm.
- The performance increase (if any) justifies the additional work others will have to do to understand your code.
- You comment thoroughly, explaining what your code does, what assumptions your comparison function makes about the input arrays, why your code will work given those assumptions, and that your method is in fact faster than the naïve method.
My gut tells me that your technique is less efficient than the obvious (to you, maybe not to me) recursive algorithm. JSON.stringify
has to recurse, anyway, in addition to the overhead involved in converting values to strings. Then, you loop through every character in the resulting string, rather than looping through elements, which are fewer in number.
精彩评论