为什么你的代码不起作用
在JavaScript中,对于像数组这样的非原始数据类型,==
和===
检查引用相等性(忽略==
可能执行的类型转换)。也就是说,它们检查arr1
和arr2
是否是内存中的同一个对象。在你的例子中,这两个数组具有相同的元素并且顺序相同,但它们并不相等。
下面是一个例子,希望能够建立直觉,即[1] === [1]
的结果是false
:
const x = [1];
const y = [1];
x === y; // false
x[0] = 200;
console.log(x); // "Array [ 200 ]"
console.log(y); // "Array [ 1 ]"
x === y; // false
解决方案
如果且仅当以下条件成立时,数组arr1
和arr2
具有相同的成员:
并且
因此,这将是解决问题的方法(ES2016):
const containsAll = (arr1, arr2) =>
arr2.every(arr2Item => arr1.includes(arr2Item))
const sameMembers = (arr1, arr2) =>
containsAll(arr1, arr2) && containsAll(arr2, arr1);
sameMembers(arr1, arr2);
这第二种使用 Underscore 的解决方案更接近于你想要的:
arr1.sort();
arr2.sort();
_.isEqual(arr1, arr2); // `true`
它能够工作是因为 isEqual
检查“深度相等”,这意味着它不仅考虑引用相等,还比较值。
你第三个问题的解决方案
你还问如何找出 arr1
中不包含在 arr2
中的元素。
这是一个解决方法 (ES2015):
const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];
arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`
你也可以使用Underscore的difference
方法:
_.difference(arr1, arr2)
更新
请参考@Redu的评论——我的解决方案适用于sameMembers
,但您可能想要的是sameMembersInOrder
,也称为deepEquals
。
更新2
如果您不关心数组成员的顺序,ES2015+的Set
可能比Array
更好。请参阅MDN有关如何使用危险的猴子补丁实现isSuperset
和difference
的说明。
更新3
如果顺序不重要,则仍然最好使用集合。但是,如果必须使用数组,则此解决方案的时间复杂度比我之前给出的解决方案更好:
function sameMembers(arr1, arr2) {
const set1 = new Set(arr1);
const set2 = new Set(arr2);
return arr1.every(item => set2.has(item)) &&
arr2.every(item => set1.has(item))
}