如何知道两个数组是否具有相同的值

IT技术 javascript arrays compare
2021-02-11 19:30:47

我有这两个数组:一个填充来自 ajax 请求的信息,另一个存储用户点击的按钮。我使用此代码(我填写了示例编号):

var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
    doSomething();
}else{
    doAnotherThing();
}

但它总是给出false,即使两个数组相同,但名称不同。(我在 Chrome 的 JS 控制台中检查了这个)。那么,有什么办法可以知道这两个数组是否包含相同的内容?为什么要给予false我怎么知道第一个数组中的哪些值不在第二个数组中?

6个回答

如果您的数组项不是对象 - 例如,如果它们是数字或字符串,您可以比较它们的连接字符串以查看它们是否以任何顺序具有相同的成员 -

var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];

if(array1.sort().join(',')=== array2.sort().join(',')){
    alert('same members');
}
else alert('not a match');
当心空项目和排序。在我的案例中,我最终使用了字符串进行比较,例如“,2,2,3”和“2,2,3”,这当然不是严格相等的。
2021-03-13 19:30:47
这将适用于具有唯一标识 toString 值的基元或对象,但不适用于任何对象。
2021-03-18 19:30:47
@alex——就我而言,字符串中允许使用逗号,但不允许使用分号,所以我使用了 ';' 加入而不是逗号
2021-03-30 19:30:47
对于字符串,即['a', 'b']可能会失败['a,b']我只会为小的一次性脚本推荐这种技术。
2021-03-31 19:30:47
嗨 kennebec,你能告诉我如何将匹配保存到另一个数组中吗?
2021-04-12 19:30:47

如果您只想检查两个数组是否具有相同的值(不管每个值的出现次数和顺序),您可以使用lodash来执行此操作

_.isEmpty(_.xor(array1, array2))

简短,简单,漂亮!

我似乎无法xor在下划线文档中找到你在考虑IODash吗?
2021-03-16 19:30:47
是的。在 2021 年并确认它适用于字符串数组。:-)
2021-04-09 19:30:47
这仅适用于整数。问题是“两个数组”而不是“两个整数数组”
2021-04-12 19:30:47

对数组进行排序并一一比较它们的值。

function arrayCompare(_arr1, _arr2) {
    if (
      !Array.isArray(_arr1)
      || !Array.isArray(_arr2)
      || _arr1.length !== _arr2.length
      ) {
        return false;
      }
    
    // .concat() to not mutate arguments
    const arr1 = _arr1.concat().sort();
    const arr2 = _arr2.concat().sort();
    
    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            return false;
         }
    }
    
    return true;
}
使用typescript Array.isArray() 导致错误,删除它工作正常。
2021-03-13 19:30:47
@canbax:您链接到的答案可能不是此处 OP 的正确答案,但它非常适合我的用例:)
2021-03-22 19:30:47
@canbax 当数组为 [1,2] 和 [1,1,2] 时,链接中的函数返回 true,在我的情况下,它们是 2 个不同的数组。虽然这个函数对这 2 个不同的数组说 false。
2021-04-05 19:30:47
排序需要 nlog(n) 时间。你不需要排序。这个答案stackoverflow.com/a/55614659/3209523在线性时间内有效。
2021-04-11 19:30:47
@LukasLiesis 提出的问题"if two arrays have the same values"所以它不是问它们是否相同。我知道它在问数组是否是相等的集合。en.wikipedia.org/wiki/Set_(数学)[1,2]并且[1,1,2]是相等的集合。它们都包含12
2021-04-11 19:30:47
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { //To test values in nested arrays
            if (!this[i].compare(testArr[i])) return false;
        }
        else if (this[i] !== testArr[i]) return false;
    }
    return true;
}

var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
    doSomething();
} else {
    doAnotherThing();
}

或许?

[2,4] [4,2] 为假。
2021-03-17 19:30:47
谢谢!它可以正常工作。我稍微修改了函数,所以我也可以知道有多少不匹配。
2021-03-21 19:30:47
@SurazKhanal 仍然需要排序
2021-04-08 19:30:47

为什么你的代码不起作用

JavaScript 有原始数据类型和非原始数据类型。

对于原始数据类型,=====检查是否在酒吧两边的东西具有相同的值。这就是为什么1 === 1是真的。

对于非原始数据类型(如数组),=====检查引用相等性。也就是说,它们检查arr1是否arr2是同一个对象。在您的示例中,两个数组具有相同顺序的相同对象,但并不等效。

解决方案

两个数组arr1andarr2具有相同的成员当且仅当:

  • 一切都arr2arr1

  • 一切都arr1arr2

所以这可以解决问题(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`

使用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); // `[4]`

更新

请参阅@Redu 的评论——我的解决方案是针对sameMembers,但您可能想到的是sameMembersInOrder也称为deepEquals

更新 2

如果你不关心数组成员的顺序,ES2015+Set可能是比Array. 请参阅有关如何实现isSupersetdifference使用危险的猴子补丁MDN 说明

更新 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))
}
你的解决方案是错误的。“两个数组 arr1 和 arr2 具有相同的成员当且仅当:arr2 中的所有内容都在 arr1 中并且 arr1 中的所有内容都在 arr2 中”这也是错误的。这是一个数组而不是一个集合。所以sameMembers([1,1,2],[2,1,2]);应该返回false。
2021-03-15 19:30:47
您的第三个解决方案arr1.filter...仅适用于检查 arr2 是否具有 arr1 的所有元素,但反之亦然。
2021-03-18 19:30:47
@Redu 猜测这取决于“相同成员”的含义——我认为它的意思是“拥有相同的成员”。sameMembers([1,1,2],[2,1,2])应该回来true,在我看来。sameMembersInOrder([1,1,2],[2,1,2])AKAdeepEquals([1,1,2],[2,1,2])应该返回false
2021-03-23 19:30:47
@gman,那些不是橙子和苹果,它们是数字,并且1 === 1. 但听起来您想检查两个数组是否具有相同顺序的相同项:在这种情况下,您将需要不同的算法。
2021-03-31 19:30:47
我的袋子里有 2 个苹果和 1 个橙子。你的袋子里有 2 个橙子和 1 个苹果。他们没有相同的成员。[1,1,2] 和 [2,1,2] 不是同一个成员。
2021-04-08 19:30:47