JavaScript has primitive data types and non-primitive data types.
For primitive data types, ==
and ===
check whether the things on either side of the bars have the same value. That's why 1 === 1
is true.
For non-primitive data types like arrays, ==
and ===
check for reference equality. That is, they check whether arr1
and arr2
are the same object. In your example, the two arrays have the same objects in the same order, but are not equivalent.
Two arrays, arr1
and arr2
, have the same members if and only if:
arr2
is in arr1
AND
arr1
is in arr2
So this will do the trick (ES2016):
const containsAll = (arr1, arr2) =>
arr2.every(arr2Item => arr1.includes(arr2Item))
const sameMembers = (arr1, arr2) =>
containsAll(arr1, arr2) && containsAll(arr2, arr1);
sameMembers(arr1, arr2); // `true`
This second solution using Underscore is closer to what you were trying to do:
arr1.sort();
arr2.sort();
_.isEqual(arr1, arr2); // `true`
It works because isEqual
checks for "deep equality," meaning it looks at more than just reference equality and compares values.
You also asked how to find out which things in arr1
are not contained in arr2
.
This will do it (ES2015):
const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];
arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`
You could also use Underscore's difference
: method:
_.difference(arr1, arr2); // `[4]`
See @Redu's comment—my solution is for sameMembers
, but what you may have in mind is sameMembersInOrder
also-known-as deepEquals
.
If you don't care about the order of the members of the arrays, ES2015+'s Set
may be a better data structure than Array
. See the MDN notes on how to implement isSuperset
and difference
using dangerous monkey-patching.