Reputation: 1109
I'm having trouble writing a correct assertion test. It works fine on single arrays but it doesn't work when testing an array of arrays. The problem seems to be with areEqualItems
but I don't know why. What am I doing wrong?
function assertArraysEqual(actual, expected, testName){
var areEqualLength = actual.length === expected.length;
var areEqualItems = actual.every(function(item, i){
return item === expected[i]
});
if(areEqualLength && areEqualItems){
console.log('passed');
} else {
console.log('FALIED [' + testName + '] Expected ' + expected + ', but got ' + actual);
}
}
var arr1 = [0,1,2,3];
var arr2 = [0,1,2,3];
var arr3 = [ [0,1,2,3], [0,1,2,3] ];
var arr4 = [ [0,1,2,3], [0,1,2,3] ];
assertArraysEqual(arr1, arr2, 'arrays should be equal'); // passed
assertArraysEqual(arr3, arr4, 'arrays should be equal'); // FALIED [arrays should be equal] Expected 0,1,2,3,0,1,2,3, but got 0,1,2,3,0,1,2,3
Upvotes: 2
Views: 1344
Reputation: 92460
You can make a very succinct equals function. Just check the edge cases where the lengths aren't equal or they aren't arrays and then recurse:
var arr3 = [[0,1,2,3], [0,1,2,3]];
var arr4 = [[0,1,2,3], [0,1,2,3]];
function equal(a, b){
if (!Array.isArray(a) || !Array.isArray(b)) return a === b
if (a.length !== b.length) return false
return a.every((item, i) => equal(item, b[i]))
}
console.log(equal(arr3, arr4))
console.log(equal([[1, 2], [3, 4]], [[2, 2], [3, 4]]))
Upvotes: 3
Reputation: 1145
Comparing the arrays (and their child arrays, and their child arrays) can become very expensive quite quickly. In addition the code you wrote, as well as the accepted answer, don't take into account associative arrays (aka objects). I would suggest converting both of the arrays into JSON strings and then compare them as strings.
function assertArraysEqual(actual, expected, testName){
if ( actual.length === expected.length && JSON.stringify(actual) == JSON.stringify(expected) ) console.log('passed');
else console.log('FALIED [' + testName + '] Expected ' + expected + ', but got ' + actual);
}
var arr1 = [0,1,2,3];
var arr2 = [0,1,2,3];
var arr3 = [ [0,1,2,3], [0,1,2,3] ];
var arr4 = [ [0,1,2,3], [0,1,2,3] ];
assertArraysEqual(arr1, arr2, 'arrays should be equal');
assertArraysEqual(arr3, arr4, 'arrays should be equal');
Upvotes: 0
Reputation: 1514
An other solution to let this job to a third party, which can be for example lodash.
Lodash has isEqual method which can do the job for you.
Check out the documentation here.
Sample code:
function assertArraysEqual(actual, expected, testName) {
if (_.isEqual(actual, expected)) {
console.log('passed');
} else {
console.log(`FALIED [${testName}] Expected ${expected}, but got ${actual}`);
}
}
Upvotes: 0
Reputation: 2646
Why don't you stringify the arrays and then compare? It will reduce your code significantly take a look.
function assertArraysEqual(actual, expected) {
const actualStr = JSON.stringify(actual);
const expectedStr = JSON.stringify(expected);
return actualStr === expectedStr;
}
Upvotes: 1
Reputation: 781731
You need to make it recurse if the element is another array.
Also, there's no point in checking if the items are equal when the lengths don't match.
It would also be better if you took the logging out of the comparison function. I had to make it conditional on whether the testName
argument was supplied, so that it wouldn't log during all the recursive calls.
function assertArraysEqual(actual, expected, testName) {
var areEqualLength = actual.length === expected.length;
var areEqualItems = areEqualLength && actual.every(function(item, i) {
if (Array.isArray(item) && Array.isArray(expected[i])) {
return assertArraysEqual(item, expected[i]);
} else {
return item === expected[i]
}
});
if (testName) {
if (areEqualItems) {
console.log('passed');
} else {
console.log('FAILED [' + testName + '] Expected ' + expected + ', but got ' + actual);
}
}
return areEqualItems;
}
var arr1 = [0, 1, 2, 3];
var arr2 = [0, 1, 2, 3];
var arr3 = [
[0, 1, 2, 3],
[0, 1, 2, 3]
];
var arr4 = [
[0, 1, 2, 3],
[0, 1, 2, 3]
];
var arr5 = [
[0, 1, 2, 3],
[0, 2, 3, 4]
];
assertArraysEqual(arr1, arr2, 'arrays should be equal'); // passed
assertArraysEqual(arr3, arr4, 'arrays should be equal'); // FALIED [arrays should be equal] Expected 0,1,2,3,0,1,2,3, but got 0,1,2,3,0,1,2,3
assertArraysEqual(arr3, arr5, 'arrays should not be equal');
Upvotes: 2
Reputation: 3543
Here is a little help on how to make it recursive:
function areArraySame(one, two) {
var length = one.length === two.length;
var allElems = one.every(function(item, i) {
if (item instanceof Array) {
return areArraySame(item, two[i]); // <-- recurse!
}
return item === two[i];
});
return length && allElems;
}
Upvotes: 1