开发者

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 and 1), or poorly-rounded numbers like 8.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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜