'Javascript Arrays - Checking two arrays of objects for same contents, ignoring order
I have two JavaScript arrays (A and B) that contain objects that I created. I want to check that all the objects in array A are contained in array B, but not necessarily in the same order.
What is the best way to do this?
Edit:
They are all actual objects, not primitives, so I will need to compare their contents and structure as well (maybe using something like JSON.stringify).
I want to do this because I'm learning Test-Driven Development, and I want to test functions that return lists of objects. I need to test whether the returned lists have the expected objects in them or not (order doesn't matter in this case).
Solution 1:[1]
If the duplicates do not matter, you can make an one-liner by using lodash. Look if the difference between two arrays is empty.
if (_(array).difference(otherArray).isEmpty()) {
// is equal ignoring order and duplicates
}
console.log(_([1,2,3]).difference([2,3,1]).isEmpty()) // -> true
console.log(_([1,2,3,3]).difference([2,3,1,1]).isEmpty()) // -> also true
Solution 2:[2]
With ES6 you could use every and some (and length).
let A = [1, 2, 3];
let B = [2, 3, 1];
// all objects in A are contained in B (A ? B)
// you can compare a <-> b however you'd like (here just `a === b`)
let AsubB = A.every(a => B.some(b => a === b));
// A and B are the same length
let sameLength = A.length === B.length;
// their contents are as equal as previously tested:
let equal = AsubB && sameLength;
Solution 3:[3]
This is probably the simplest method if not the slowest.
var o = { PropA: 1, PropB: 2 };
var a = [1, 2, 3, 4, o];
var b = [2, 3, 4, 1];
var c = a.filter(function(value, index, obj) {
return b.indexOf(value) > -1;
});
if (c.length !== a.length) {
throw new Error("Array b is missing some elements!");
}
indexOf will only check that they refer to the same object. If you want to check value equivalence you will have to do a deep compare of the properties or use JSON.stringify as you mention in your question.
Solution 4:[4]
Simple & Elegant
function isEqual(arr1, arr2) {
if (arr1.length !== arr2.length)
return false;
return arr1.every(x => arr2.includes(x));
}
If duplication is important, use this
function isEqual(arr1, arr2) {
if (arr1.length !== arr2.length)
return false;
arr1.sort();
arr2.sort();
for (var i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i])
return false;
}
return true;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Jari Keinänen |
| Solution 3 | |
| Solution 4 |
