I know I can do it using loops, but I'm trying to find an elegant way of doing this:
I have two jagged arrays (array of arrays):
var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];
I want to use lodash to confirm that the above two jagged arrays are the same. By 'the same' I mean that there is no item in array1 that is not contained in array2. Notice that the items in jagged array are actually arrays. So I want to compare between inner arrays.
In terms of checking equality between these items:
['a', 'b'] == ['b', 'a']
or
['a', 'b'] == ['a', 'b']
Both work since the letters will always be in order.
UPDATE: Original question was talking about to "arrays" (instead of jagged arrays) and for years many people discussed (and added answers) about comparing simple one-dimensional arrays (without noticing that the examples provided in the question were not actually similar to the simple one-dimensional arrays they were expecting).
If you sort the outer array, you can use _.isEqual() since the inner array is already sorted.
var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];
_.isEqual(array1.sort(), array2.sort()); //true
Note that .sort() will mutate the arrays. If that's a problem for you, make a copy first using (for example) .slice() or the spread operator (...).
Or, do as Daniel Budick recommends in a comment below:
_.isEqual(_.sortBy(array1), _.sortBy(array2))
Lodash's sortBy() will not mutate the array.
You can use lodashs xor for this
doArraysContainSameElements = _.xor(arr1, arr2).length === 0
If you consider array [1, 1] to be different than array [1] then you may improve performance a bit like so:
doArraysContainSameElements = arr1.length === arr2.length && _.xor(arr1, arr2).length === 0
There are already answers here, but here's my pure JS implementation. I'm not sure if it's optimal, but it sure is transparent, readable, and simple.
// Does array a contain elements of array b?
const union = new Set([...a, ...b]);
const contains = (a, b) => union.size === a.length && union.size === b.length;
// Since order is not important, just data validity.
const isEqualSet = (a, b) => union.contains(a, b) || union.contains(b, a)
The rationale in contains() is that if a does contain all the elements of b, then putting them into the same set would not change the size.
For example, if const a = [1,2,3,4] and const b = [1,2], then new Set([...a, ...b]) === {1,2,3,4}. As you can see, the resulting set has the same elements as a.
From there, to make it more concise, we can boil it down to the following:
const isEqualSet = (a: string[], b: sting[]): boolean => {
const union = new Set([...a, ...b])
return union.size === a.length && union.size === b.length;
}
Edit: This will not work with obj[{a: true}, true, 3] but does compare array contents probably as long as they are primitive elements. Method fixed and tested against strings two arrays using the same values in different orders. Does not work with object types. I recommend making a universal helper which calls a helper function depending on the type which needs to be compared. Try _.isEqual(a. b); from the very fantastic lodash library.