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

问题描述 投票:78回答:12

我有这两个数组:一个填充来自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?我如何知道第一个数组中的哪些值不在第二个数组中?

javascript arrays compare
12个回答
16
投票
function arraysEqual(_arr1, _arr2) {

    if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
      return false;

    var arr1 = _arr1.concat().sort();
    var arr2 = _arr2.concat().sort();

    for (var i = 0; i < arr1.length; i++) {

        if (arr1[i] !== arr2[i])
            return false;

    }

    return true;

}

请注意,与先前的答案不同,这不会修改原始数组。


1
投票

我在Game项目中有简单的整数值 每个数组中的值数量较少,也需要原始数组不变 所以,我做了以下,它工作得很好。 (编辑代码粘贴在这里)

var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];

if (sourceArray.length !== targetArray.length) {
    // not equal
    // did something
    return false;
}

var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();

if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
    // not equal
    // did something
    return false;
}
else {
    // equal
    // did something
    // continued further below
}

// did some more work

return true;

希望有所帮助。


1
投票

Using ES6

我们将使用Ramda的equals函数,但我们可以使用Lodash或Underscore的isEqual

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

使用扩展运算符,我们避免改变原始数组,并保持我们的函数纯。


0
投票

请检查这个答案

var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
    var array2=arr2[j];
    if(array1==array2)
    {
return true;
    }
}
}

0
投票

如果数组中的项目是基元(数字或单个字符),则可以使用比较长度和使用集合的组合。

function equalArrayItems(arr1, arr2) {
  if (arr1.length !== arr2.length) return false
  const set1 = new Set(arr1)
  const set2 = new Set(arr2)
  const set3 = new Set(arr1, arr2)
  return set1.size === set3.size && set2.size === set3.size
}

72
投票

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

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');

42
投票
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();
}

也许?


40
投票

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

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

简短,漂亮!


23
投票

Why your code didn't work

JavaScript具有primitive data types和非原始数据类型。

对于原始数据类型,=====检查条形图两侧的内容是否具有相同的值。这就是为什么1 === 1是真的。

对于像数组这样的非原始数据类型,=====检查引用相等性。也就是说,他们检查arr1arr2是否是同一个对象。在您的示例中,两个数组具有相同顺序的相同对象,但不等效。

Solutions

当且仅当以下情况时,两个数组arr1arr2具有相同的成员:

  • arr2的一切都在arr1

  • 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); // `true`

使用Underscore的第二个解决方案更接近你想要做的事情:

arr1.sort();
arr2.sort();

_.isEqual(arr1, arr2); // `true`

它的工作原理是因为isEqual检查“深度相等”,这意味着它不仅仅是参考相等并且比较值。

A solution to your third question

您还询问了如何找出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]`

UPDATE

请参阅@Red的评论 - 我的解决方案适用于sameMembers,但您可能想到的是sameMembersInOrder,也称为deepEquals

UPDATE 2

如果你不关心数组成员的顺序,ES2015 +的Set可能是比Array更好的数据结构。使用危险的猴子修补程序查看MDN notes on how to implement isSuperset and difference


6
投票

对象相等性检查:JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

上述测试也适用于对象数组,在这种情况下使用http://www.w3schools.com/jsref/jsref_sort.asp中记录的排序函数

对于具有平坦JSON模式的小数组,可能就足够了。


3
投票

比较这两个数组时,您要比较代表数组的对象,而不是内容。

你必须使用一个函数来比较两者。您可以自己编写一个简单的循环,然后在检查长度是否相同之后将其与另一个进行比较。


2
投票

我们的目标基本上是检查2个数组是否相等。这里设置意味着数学set。渐近最快的排序需要O(nlog(n))时间。您可以使用字典数据结构渐进式O(n)时间。在JS中,字典只是一个带有键和值的对象。

// assumes array elements are primitive types
function areArraysEqualSets(a1, a2) {
  let superSet = {};
  for (let i = 0; i < a1.length; i++) {
    const e = a1[i] + typeof a1[i];
    superSet[e] = 1;
  }

  for (let i = 0; i < a2.length; i++) {
    const e = a2[i] + typeof a2[i];
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

  for (let e in superSet) {
    if (superSet[e] === 1) {
      return false;
    }
  }

  return true;
}

请注意,此函数适用于基本类型的数组,并假设a1和a2是数组


1
投票

如果您使用的是Prototype Framework,则可以使用数组的intersect方法找出它们是否相同(无论顺序如何):

var array1 = [1,2];
var array2 = [2,1];

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}
© www.soinside.com 2019 - 2024. All rights reserved.