As the title says I want to compare two js arrays in which I only care about the contents being the same, but I don't care about the order of them being the same. So what I would expect is this:
[1, 2, 3, 3] == [1, 2, 3, 3] // True
[1, 2, 3, 3] == [1, 3, 2, 3] // True
[1, 2, 3, 3] == [1, 2] // False
[1, 2, 3, 3] == [1, 2, 3] // False
[1, 2, 3, 3] == [1, 2, 3, 3, 3] // False
[1, 2, 3, 3] == [1, "2, 3, 3"] // False
Obviously the comparison operator doesn't work. From this SO answer I got the Array.prototype method below, but that unfortunately also checks if the order is the same.
So does anybody know how I can check if two js arrays contain the same elements, not taking into account the order of the elements? All tips are welcome!
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
sort them before comparing:
from the comment below, if you want the 2 arrs to contain different primitive type.add this sort function.
function s(x,y){
var pre = ['string' , 'number' , 'bool']
if(typeof x!== typeof y )return pre.indexOf(typeof y) - pre.indexOf(typeof x);
if(x === y)return 0;
else return (x > y)?1:-1;
}
var arr1 = [1, 2, 3, 3].sort(s);
var arr2 = [1, 3, 2, 3].sort(s);
arr1.equals(arr2);// true
Here is a solution that works for primitive values. It uses an object as a primitive map and counts the number of occurrences of each value. However, it also considers the data type of each value.
It checks the length of the arrays first, as shortcut:
function equals(a, b) {
if (a.length !== b.length) {
return false;
}
var seen = {};
a.forEach(function(v) {
var key = (typeof v) + v;
if (!seen[key]) {
seen[key] = 0;
}
seen[key] += 1;
});
return b.every(function(v) {
var key = (typeof v) + v;
if (seen[key]) {
seen[key] -= 1;
return true;
}
// not (anymore) in the map? Wrong count, we can stop here
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With