JS - How can I check if 2 arrays contains the same values
Given I have 2 number arrays. How can I check efficiently if the values are same?
I would prefer vanilla JavaScript solution without third party library ๐
2033 views
Given I have 2 number arrays. How can I check efficiently if the values are same?
I would prefer vanilla JavaScript solution without third party library ๐
2033 views
It seems like some of these answers missed the efficiently part.
First off, you didn't specify if [1, 2, 3]
is the same as [1, 3, 2]
. But let's assume they aren't the same. Generating strings using join is way slower than just checking in a loop
function hasSameValuesInSameOrder(a, b) {
if (a.length !== b.length) return false;
const len = a.length;
for (let i = 0; i < len; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
It doesn't matter if the arrays are the same or different but if the are different checking one element at a time is going exit early where as joining the arrays touches every element, on top of converting numbers to strings and all of those strings into a bigger string which all adds up to being super inefficient.
According to this benchmark using join is 1000x slower than just comparing in a loop. The best case for join will be if the arrays are the same but it will still be slower.
If [1, 2, 3] is the same as [1, 3, 2] then sorting will solve it but sorting in the compare function like one of the answers would be poor design because sort modifies the arrays. You would not expect a function that's only supposed to tell you if 2 arrays contain the same values to change your arrays. So, if you want to use sort then you need to make a copy of the arrays
function hasSameValues(a, b) {
if (a.length !== b.length) { return false; }
// changing the original arrays would be evil so we
// have to make copies.
const aSorted = a.slice().sort();
const bSorted = b.slice().sort();
const len = aSorted.length;
for (let i = 0; i < len; ++i) {
if (aSorted[i] !== bSorted[i]) {
return false;
}
}
return true;
}
but the copy and the sort take time. Sort speed is O(n log n).
We could also compare using a map. We'd use the map to count each value in the first array, then subtract from those counts with the second array. If any count is missing or goes below 0 they didn't contain the same values
function hasSameValues(a, b) {
if (a.length !== b.length) { return false; }
const counts = new Map();
for (const v of a) {
const count = counts.get(v) || 0;
counts.set(v, count + 1);
}
for (const v of b) {
const count = counts.get(v);
if (!count) { // undefined or 0, both mean arrays are not the same
return false;
}
counts.set(v, count - 1);
}
return true;
}
This should effectively be less than O(n) time. Comparing these 3 methods, the join
method is the slowest. The map
method is the fastest by far
Note: I'm also assuming since you said you wanted to compare arrays of numbers that you actually passed in "arrays of numbers", not objects that look like arrays of numbers, not typedarrays, etcโฆ so checking Array.isArray
is a waste of time.
[6, -2, 2, 6, -7]
, calling .sort()
on it will produce a wrong result [ -2, -7, 2, 6, 6 ]
because sort()
by default treats each element of the array as a string. This can easily be fixed by writing the comparison function to be used by sort()
: [ -2, -7, 2, 6, 6 ].sort((a, b) => a - b )
Since OP asked for a vanilla solution, my answer is very similar to @Anki Batsukh's, only I removed type annotations, which are not vanilla JS and added a few more checks before actually comparing the arrays.
function hasSameValues(arr1, arr2) {
if (!arr1 || !arr2) {
return false
}
if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
return false
}
if (arr1.length !== arr2.length) {
return false
}
return arr1.join('|') === arr2.join('|')
}
If performance is important for you, I would recommend you to check the array length first. You could create an util function like this:
function hasSameValues(arr1: number[], arr2: number[]): boolean {
if (arr1.length !== arr2.length) {
return false;
}
return arr1.join('|') === arr2.join('|');
}
If the values in your array does not necessarily have to have the same order then you should sort them before join()
arr1.sort().join('|') === arr2.sort().join('|');