1

Look at these examples of array comparative code:

// example-1
let array1 = ['a', 'b'];
let array2 = ['a', 'b'];
console.log(array1.equals(array2)); // returns true

// example-2
let array1 = ['a', 'b', 1];
let array2 = ['a', 'b', 1];
console.log(array1.equals(array2)); // returns true

// example-3
let array1 = ['a', 'b', {'a': 1, 'b': 2}];
let array2 = ['a', 'b', {'b': 2, 'a', 1}];
console.log(array1.equals(array2)); // returns false

I'm looking for a way to compare the arrays containing objects in them, but irrespective of the order of elements in a nested object, like mentioned in the example-3 above.

Teemu
  • 22,918
  • 7
  • 53
  • 106
Akshay Maldhure
  • 787
  • 2
  • 19
  • 38
  • 2
    Possible duplicate of [How to compare arrays in JavaScript?](https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript) – holydragon Dec 20 '18 at 07:03
  • @holydragon I don't think so, since the other question does not specifically ask about the condition for the arrays to contain JSON objects within them, like I have mentioned here. – Akshay Maldhure Dec 20 '18 at 07:06
  • How did you got the [JSON object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON)s to the array in the first place? – Teemu Dec 20 '18 at 07:14
  • An array could contain any kind of objects including JSON objects, right? – Akshay Maldhure Dec 20 '18 at 07:15
  • For sure yeah, but there's no JSON objects, just JS objects ... – Teemu Dec 20 '18 at 07:16
  • Please don't use JSON in your question, since there's no JSON at all involved in the question. Using JSON here is just as bad as I called you Akshaya ... – Teemu Dec 20 '18 at 07:23
  • @Teemu Sorry, I'm quite new to Node.js and I did not understand the difference between JSON object and JS object. In what way are they different? – Akshay Maldhure Dec 20 '18 at 07:37
  • 1
    JSON object is an intrinsic object in browsers, it contains the methods like `stringify` and `parse`. JS object is just a JS object, that's what you have. JSON is a textual data interchange format, it is language independent, and has noting to do with JS objects, except a part of JSON strings can look distictly similar. – Teemu Dec 20 '18 at 07:41
  • **Moderator Note:** Please don't roll back valid changes. – Bhargav Rao Dec 20 '18 at 09:35
  • @BhargavRao I did it by mistake. I'm sorry about that. – Akshay Maldhure Dec 20 '18 at 09:35

4 Answers4

2

You should JSON.stringify() the arrays and compare them like so:

var arr1 = ['a', 'b', {'a': 1}];
var arr2 = ['a', 'b', {'a': 1}];
console.log(JSON.stringify(array1) == JSON.stringify(array2)); 

This works because it converts arrays of objects into a much simpler comparative state (JSON strings). This will only work if the arrays contain their properties in the same ordered in the OP's example.

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
1

You can use JSON.stringify() to get the JSON string and compare them with ===:

let array1 = ['a', 'b', {'a': 1}];
let array2 = ['a', 'b', {'a': 1}];
console.log(JSON.stringify(array1) === JSON.stringify(array2)); // returns true
Giulio Bambini
  • 4,695
  • 4
  • 21
  • 36
1

underscore way:

_.isEqual(array1, array2) 
sadrzadehsina
  • 1,331
  • 13
  • 26
  • Thank you. The only reason I would prefer `JSON.stringify()` over `underscore` is that the prior one won't need me to install any extra modules in node.js. Do you see any potential case with which `JSON.stringify()` would fail? – Akshay Maldhure Dec 20 '18 at 07:14
  • 2
    It does not work if the key is not in order, `['a', 'b', {'a': 1, 'b': 2}]` and `['a', 'b', {'b': 2, 'a': 1}]` are the same but `JSON.strigify` wont work in this situation. You may have to sort them before comparing that cause an extra payload – sadrzadehsina Dec 20 '18 at 07:16
  • Amazing. That makes me accept this as an answer since I want the comparison to be order-agnostic. Thank you! – Akshay Maldhure Dec 20 '18 at 07:20
  • 2
    you can also use `lodash` a light version of `underscore` - https://lodash.com/docs/#isEqual – sadrzadehsina Dec 20 '18 at 07:21
0

You can just write a function the will recursively check until it gets down to primitives. For example:

function deepEqual(o1, o2){
    if (Array.isArray(o1)) {
        return Array.isArray(o2)
               && o1.length === o2.length
               && o1.every((item, idx) => deepEqual(item, o2[idx]))
    }
    if (typeof(o1) == 'object' && o1 != null){ // (typeof null == 'object)
        return typeof(o2) == 'object'
               && o2 != null
               && deepEqual(Object.entries(o1)
                  .sort((a,b) => a[0].localeCompare(b[0])),Object.entries(o2).sort((a,b) => a[0].localeCompare(b[0])))
    }
    return o1 === o2
}

//Object order doesn't matter
let ob1 = [1, 2, {a: "test", b:"hello"}, 4]
let ob2 = [1, 2, {b:"hello", a: "test", }, 4]

console.log(deepEqual(ob1, ob2))

ob1 = [1, 2, {a: "test", b:"hello"}, 4]
ob2 = [1, 2, {b:"hello", a: "non-test", }, 4]

console.log(deepEqual(ob1, ob2))

// array order matters:
ob1 = [2, 1, {a: "test", b:"hello"}, 4]
ob2 = [1, 2, {b:"hello", a: "test", }, 4]

console.log(deepEqual(ob1, ob2))

console.log(deepEqual("test", "test"))

console.log(deepEqual(null, {a:"test"}))

// etc.
Mark
  • 90,562
  • 7
  • 108
  • 148