DEV Community

Cover image for Simplest way to compare two numbers array in JS
Shuvo
Shuvo

Posted on

Simplest way to compare two numbers array in JS

In case of string we can simply use == or === to see if they are same but we can't use those to see in two arrays are similar or in other words they have same elements.
So this wont work.

const array1 = [1, 2, 3, 4, 5]
const array2 = [1, 2, 3, 4, 5]
console.log(array1 == array2) //false
Enter fullscreen mode Exit fullscreen mode

But what if we convert our array to string? Then you can use the comparison operator. This makes the task very easy. We can sort an array using toString method eg. array1.toString() or we can use this hack

console.log([1, 2, 3, 4, 5] + "")
//logs 1,2,3,4,5
console.log(typeof ([1, 2, 3, 4, 5] + ""))
//logs string
Enter fullscreen mode Exit fullscreen mode

So basically if we try to concatenate string(empty string in this case) to an array the array will be converted to a string.
so now we can simply use the arrays as strings and compare them

const array1 = [1, 2, 3, 4, 5]
const array2 = [1, 2, 3, 4, 5]
console.log(array1 + "" == array2 + "") //true
Enter fullscreen mode Exit fullscreen mode

Also if you want it to work with arrays where the elements are not in order you can first sort them. Let's create a utility function for that

function compareArr(arr1, arr2){
    arr1.sort()
    arr2.sort()
    return arr1 + "" == arr2 + ""
}
const array1 = [1, 2, 3, 4, 5]
const array2 = [1, 5, 2, 4, 3]
console.log(compareArr(array1, array2)) // returns true
Enter fullscreen mode Exit fullscreen mode

Discussion (52)

Collapse
ksengine profile image
Kavindu Santhusa • Edited on

Correct Algorithm

Here is the Correct Algorithm

const array1 = [1, 2, 3, 4, 5];
const array2 = [1, 2, 3, 4, 5];

// This is the function
const compare = (a1, a2) =>
  a1.length == a2.length &&
  a1.every(
    (element, index) => element === a2[index]
  );

// Example
console.log(compare(array1, array2));

// Sorted
console.log(compare(array1.sort(), array2.sort()));
Enter fullscreen mode Exit fullscreen mode
Collapse
marcosteinke profile image
Marco Steinke

This was the solution for a subtask of a problem I recently solved in a project.

I compared two vectors element-wise and counted the amount of distinct elements

getTotalDifference(anotherVector) {
    let diff = 0;
    this.values.forEach((e,i) => { return (this.values[i] != anotherVector[i]) ? diff++ : diff = diff; })
    return diff;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
0shuvo0 profile image
Shuvo Author

And your function has some drawbacks also
algo fail

Collapse
darkwiiplayer profile image
DarkWiiPlayer

Whether that's a drawback or by design is questionable; whether two identical objects should be treated as actually the same completely depends on your problem domain.

Thread Thread
0shuvo0 profile image
Shuvo Author

agreed 100%

Collapse
ksengine profile image
Kavindu Santhusa

In js your Objects are not equal
If your arrays are

const num5 = { num: 5 };
const array1 = [1, 2, 3, 4, num5];
const array2 = [1, 2, 3, 4, num5];
Enter fullscreen mode Exit fullscreen mode

It works.

Collapse
virtualghostmck profile image
virtualghostmck

If a2 has more elements than a1, then this algo fails.

Collapse
ksengine profile image
Kavindu Santhusa

Thanks, Now it's upadated.

Collapse
hnicolas profile image
Nicolas Hervé

You forgot to compare array sizes.

compare([1], [1, 2]); // true
Enter fullscreen mode Exit fullscreen mode
Collapse
0shuvo0 profile image
Shuvo Author

Yes but we are talking about the simple approach here

Collapse
ilumin profile image
Teerasak Vichadee

I think it would be greate if we sort the array inside compare function, so we can sure that it will compare with the right position

Collapse
valeriavg profile image
Valeria

This method will not work for non-primitive values:

[{v:1},{v:2},{v:3}] + ''
// '[object Object],[object Object],[object Object]'
Enter fullscreen mode Exit fullscreen mode

Although slight alteration to the algorithm will do the trick:

JSON.stringify([{v:1},{v:2},{v:3}])
// '[{"v":1},{"v":2},{"v":3}]'
JSON.stringify([1,2,3,4,5])
// '[1,2,3,4,5]'
Enter fullscreen mode Exit fullscreen mode

However even the latter comparison is aimed for simple and small arrays as it can be pretty expensive and yield unexpected results for some edge-cases, e.g.:

JSON.stringify(new Set([1,2,3]))
// '{}'
Enter fullscreen mode Exit fullscreen mode

In those cases one can use deep equal implementation from a variety of packages.

Collapse
darkwiiplayer profile image
DarkWiiPlayer

This method will not work for non-primitive values

I read that as "non-prime values" at first and was severely confused 😆

Collapse
0shuvo0 profile image
Shuvo Author

true, most short hacks usually have drawbacks

Collapse
ksengine profile image
Kavindu Santhusa

Your solution has too many drawbacks.

Thread Thread
pierrewahlberg profile image
Pierre Vahlberg

That was not very constructive really. Care to explain a bit what the drawbacks could be?

Collapse
wxs77577 profile image
Johnny Wu

also you can use lodash.isMatch _.isMatch

Collapse
suckup_de profile image
Lars Moelleken • Edited on

Last time I needed to compare sommeting in JS I used "JSON.stringify" but its still a hack. What is the correct way to do it nowadays? 🤔

Collapse
valeriavg profile image
Valeria

There is no general right or wrong as it depends on a particular use case, but if you want an optimal solution that would handle most of the cases it'll probably be a recursive iterator over indices with early return.

Collapse
0shuvo0 profile image
Shuvo Author

Writing an algorithm with loop and recursion if needed

Thread Thread
ksengine profile image
Kavindu Santhusa

Extractly

Collapse
patricktingen profile image
Patrick Tingen

What's the advantage of using the "hack" over the more straightforward way of adding .toString? The advantage of .toString is that it makes your intent more clear, which might be a tiny bit more maintenance friendly

Collapse
0shuvo0 profile image
Shuvo Author

There are two types of people in this world.

  1. People who like hacks
  2. Other people
Collapse
patricktingen profile image
Patrick Tingen

Haha, fair enough, but type-1 people then better keep working in 1-person teams

Thread Thread
0shuvo0 profile image
Shuvo Author

Yes in corporate/serious project you have some rules to follow

Collapse
blackr1234 profile image
blackr1234 • Edited on

I won't consider that a "hack" because as a Java developer I always write +"" instead of toString(), but I would consider stringifying the arrays and comparing them a hack for array comparison.

Thread Thread
0shuvo0 profile image
Shuvo Author

Owh nice to know

Collapse
hnicolas profile image
Nicolas Hervé

This is so wrong...

compareArr([1, 2, 3], [1, "2,3"]);
Enter fullscreen mode Exit fullscreen mode
Collapse
0shuvo0 profile image
Shuvo Author

actually I was aiming for numbers array. I updated the title
Thanks

Collapse
hnicolas profile image
Nicolas Hervé
Array.prototype.toString = () => "oups";
compareArr([1, 2, 3], [4, 5, 6]);
Enter fullscreen mode Exit fullscreen mode
Thread Thread
ksengine profile image
Kavindu Santhusa

Changing built-in Objects is a bad idea.

Thread Thread
hnicolas profile image
Nicolas Hervé

It is a bad practice, but in the browser context you should be aware that object prototype pollution exists.

Collapse
0shuvo0 profile image
Shuvo Author

didn't saw that coming

Collapse
lukeshiru profile image
LUKESHIRU • Edited on

I would say that more than "simplest" it would be "hackiest", because you're using string coercion to compare them, and you're mutating the given arguments with Array.prototype.sort. So ideally if you want to keep the logic similar, you'll still need to do something like this:

const compareArr = (arr1, arr2) =>
    [...arr1].sort().toString() === [...arr2].sort().toString();
Enter fullscreen mode Exit fullscreen mode

Still, is not that useful to compare two arrays that have different order in their elements as equal. If you actually implement a proper comparison in the future, then the order of the elements matter.

There are some great packages out there to achieve this, one I recommend is dequal by lukeed.

Collapse
joeattardi profile image
Joe Attardi

Please don't ever do this in production code.

Collapse
0shuvo0 profile image
Shuvo Author

Agreed

Collapse
joeattardi profile image
Joe Attardi

So you agree that your own post is a bad idea? 🤔

Thread Thread
0shuvo0 profile image
Shuvo Author

yes there is always drawbacks of easy hacks.
But if you're confident about your input you might as well ues this

Thread Thread
joeattardi profile image
Joe Attardi

Sometimes hacks make it into production code and become technical debt. This is not a hack that should ever be in a real application.

There are a lot of beginners on DEV and when they see posts like this it teaches them really bad practices. Particularly here since you have tagged it with #beginners.

Besides, your "solution" is for comparing arrays of numbers only. Comparing two arrays containing just numbers is easy with a simple loop since there aren't nested properties, etc.

function arrayEquals(arr1, arr2) {
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] !== arr2[i]) {
      return false;
    }

    return true;
}
Enter fullscreen mode Exit fullscreen mode

You could also use Array.prototype.every for a one-liner:

function arrayEquals(arr1, arr2) {
  return arr1.every((el, index) => arr2[index] === el);
}
Enter fullscreen mode Exit fullscreen mode

With both of the above approaches, it bails out as soon as it finds two array elements that are not unique. Stringifying and comparing strings (yuck) requires processing each array in full.

Collapse
tamusjroyce profile image
tamusjroyce

Check the length first. That is the simplest way to tell they may not be equivalent. You have also just sorted the original array1 and array2. ‘[…array2].sort()’ would be better.

array1.length === array2.length && array1.some???

Collapse
j7222 profile image
J7222 • Edited on

let x=['1',2,5,6];
let y= [1,2,5,6];
let xlenx = x.length;
for(let i=0;i<xlenx;i++){
if(x[i]==y[i]){

console.log(x[i] + ' == ' + y[i])
}
else if(x[i]!==y[i]){
console.log('not same');
break;
}}

Collapse
lexlohr profile image
Alex Lohr

A faster way of unsorted equality would be:

const arrayEqualsUnsorted = (array1, array2) =>
  array1.length === array2.length && 
  array1.every(item => array2.includes(item));
Enter fullscreen mode Exit fullscreen mode
Collapse
hnicolas profile image
Nicolas Hervé

It don"t work with duplicated values.

arrayEqualUnsorted([1, 1, 2], [1, 2, 2]); // true
Enter fullscreen mode Exit fullscreen mode
Collapse
jt3k profile image
Andrey Gurtovoy • Edited on
compareArr = (arr1, arr2) => {
  if(arr1.length !== arr2.length){ return false;}
  return arr1.every((item, index) => item === arr2[index]);
};
Enter fullscreen mode Exit fullscreen mode

// Is better for your task

Collapse
killshot13 profile image
Michael R.

Ahh! I love the smell of a lively Javascript debate thread in the morning, now to peruse (creep) on all the comments whilst remaining quiet as a church mouse. 😅😁😶

Collapse
0shuvo0 profile image
Shuvo Author

I also should've done that

Collapse
jdforsythe profile image
Jeremy Forsythe

Your function mutates the arrays. After calling compareArr(), array2 will have been sorted. You should copy the arrays before sorting so you don't mutate the parameters

Collapse
planet_cbx profile image
Charlène Bonnardeaux

I don't think that's a good practice, only because two arrays may contain the same thing but not in the same order... I would tend to just iterate on one and do a comparison with each of the values

Collapse
blackr1234 profile image
blackr1234

If order matters, don't sort them before converting to strings. Yeah of course you could loop them, or use utility libraries.

Collapse
coderduck profile image
duccanhole

but if we compare [1,'2',3] and [1,2,3]; I expect false, and result is true

Collapse
0shuvo0 profile image
Shuvo Author

yes that's why in the post title I said numbers array

Collapse
capscode profile image
capscode

There is one amazing Library called underscore to object comparison