Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sometimes I'll need to compare to data structures (e.g. an object or array) to determine whether they have the same members and member values.

To this end, I've written Object.identical.js().

Object.identical = function (a, b, ignoreOrder) {

   function sort(o) {

      if (Array.isArray(o)) {
            return o.sort();
      }
      else if (typeof o === "object") {
         return Object.keys(o).sort().map(function(key) {
            return sort(o[key]);
         });
      }

      return o;
   }

   if (ignoreOrder === true) {
      a = sort(a);
      b = sort(b);
   }

   return JSON.stringify(a) === JSON.stringify(b);
} 

Any feedback?

One specific question I have is, because the script uses ECMAScript5 Array.isArray() and Object.keys(), should I convert my Object.identical.js script to not use them and instead use code that would work in previous versions of ECMAScript? I believe I would just have to change two lines of code, and add two.

Feedback wanted! Thanks!

share|improve this question
2  
From the faq: "Make sure you include your code in your question." With that in mind I've edited your code into the post. It makes it easier for others to see what you're refering to without having to click to another page. – Michael K Mar 21 '11 at 18:32

4 Answers

First off, about the "name" of the function: I'm not sure if extending the Object object is a good idea. It wasn't until recently (ECMAScript5 agian), that Object didn't have any such "class methods", and I don't know if other scripts may trip over them.


I don't know if it's by design, but if not, your code has a serious bug: When comparing two objects with ignoreOrder == true, then your function will return true, when the objects have different member names, but the same member values, for example:

Object.identical({a:1, b:2}, {x: 1, y:2}, true); //returns true

Personally I find distinguishing between "sorted" and "unsorted" objects or "sorting" objects at all a bit strange, because by definition the members of an object don't have an order. For all intents and purposes {a: 1, b: 2} and {b: 2, a: 1} are identical and should be always handled that way. This also leads to wondering if stringify() is the right tool to compare objects, because that wouldn't considered those two examples the same.

I think functions as defined in this StackOverflow question as much more reliable and in the spirit of how JavaScript objects are defined.

share|improve this answer

Here is a table of all the browsers that support ECMAScript5. It looks like only the newest browsers (FF4, IE9) support it, so if you're only running on those or are willing to limit your site to those, you're fine. Otherwise, refactor to earlier code.

This SO answer gives a JavaScript solution to equality that I believe will work more widely.

share|improve this answer
Appreciate the input. Whwne you say you believe it will work "more widely," can you give me an example? – user2718 Mar 21 '11 at 18:55
By "more widely" I just mean on more browsers. I'm not an expert on JavaScript compatability, but in that example I didn't see anything that wouldn't work in IE7, which is the browser I support at work. – Michael K Mar 21 '11 at 18:59

All technical questions aside, I don't really see a big need for such a function. Any sane programmer would try to avoid using such an expensive function, and I just can't think of any legitimate situation where you want a complete compare.

share|improve this answer
Trust me, I've needed this sort of thing before. – Peter Olson Oct 27 '11 at 2:06
@PeterOlson The question is, did you need it, or did you just think you needed it because you couldn't find a better way to deal with the problem? – eBusiness Oct 27 '11 at 5:30

I would separate array and object comparison.

And for arrays, another way to proceed can also be to use the algorithm given here: http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/

function getArrayWithoutDuplicates (anArray) { //derived from shamasis.net
    var o = {}, i, l = anArray.length, r = [];
    for(i=0; i<l;i+=1) o[anArray[i]] = anArray[i];
    for(i in o) r.push(o[i]);
    return r;
};

function arrayCompare(array1, array2, ignoreOrder){
    if(array1.length != array2.length) {return false;}

    var wdArray1 = getArrayWithoutDuplicates(array1);
    var wdArray2 = getArrayWithoutDuplicates(array2);
    if(ignoreOrder){
        wdArray1 = sort(wdArray1);
        wdArray2 = sort(wdArray2);
    }
    for(var i = 0; i < wdArray1.length; i++){
        if(wdArray1[i] != wdArray2[i]){return false;}
    }
    //If not returned until there, then arrays are identical
    return true;
}

This could be used depending on your needs in terms of performance, and the performance of JSON.stringify compared to this algorithm.

share|improve this answer
I like that you do the simple, efficient check with.length first... Why do you use getArrayWithoutDuplicates? There could be a edge case where the length is the same, the duplicates are different though (when not sorting)... – thomasf1 Jan 13 at 18:13
And a small fix: wdArray1 = sort(wdArray1); should be wdArray1 = wdArray1.sort(); I guess :) – thomasf1 Jan 13 at 18:41
Yes thomasf1, I think the wdArray1 = wdArray1.sort() is the correct sentence. Why I use getArrayWithoutDuplicates ? I did not touch to Javascript code since end 2011 so I don't remember what I had in mind. May be was it useful for the project I was working on. Thinking about this now, it seems that it was not a so good idea and I would remove it now. The simplest it is, the best it is... ;) – lauhub Jan 13 at 22:40
No worries :)... Have fun coding, cheers from Berlin – thomasf1 Jan 14 at 1:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.