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

Car*_*oso 84 javascript arrays compare

我有这两个数组:一个填充来自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();
}
Run Code Online (Sandbox Code Playgroud)

但它始终给出false,即使两个数组相同,但名称不同.(我在Chrome的JS控制台中查看了这个).那么,有什么方法可以知道这两个数组是否包含相同的数据?它为什么要给予false?我如何知道第一个数组中的哪些值不在第二个数组中?

ken*_*bec 75

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

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');
Run Code Online (Sandbox Code Playgroud)

  • 这将适用于具有唯一标识 toString 值的基元或对象,但不适用于任何对象。 (3认同)
  • 注意空项和排序.我最后在我的情况下用字符串来比较,如"2,2,3"和"2,2,3",这当然不是严格相等的. (3认同)
  • 可能无法输入字符串,例如`['a','b']`和`['a,b']`。我只推荐这种技术用于小的一次性脚本。 (2认同)

Tec*_*nic 43

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

_.isEmpty(_.xor(array1, array2))
Run Code Online (Sandbox Code Playgroud)

简短,漂亮!

  • 是的。2021 年,并确认它适用于字符串数组。:-) (4认同)

isa*_*son 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();
}
Run Code Online (Sandbox Code Playgroud)

也许?

  • 修改内置类型是一个坏主意。 (2认同)

Max*_*ber 23

为什么你的代码不起作用

JavaScript具有原始数据类型和非原始数据类型.

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

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

解决方案

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

  • 一切都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`
Run Code Online (Sandbox Code Playgroud)

使用Underscore的第二个解决方案更接近您尝试执行的操作:

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

_.isEqual(arr1, arr2); // `true`
Run Code Online (Sandbox Code Playgroud)

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

第三个问题的解决方案

您还询问了如何找出arr1未包含的内容arr2.

这样做(ES2015):

const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];

arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`
Run Code Online (Sandbox Code Playgroud)

你也可以使用Underscore的difference方法:

_.difference(arr1, arr2); // `[4]`
Run Code Online (Sandbox Code Playgroud)

UPDATE

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

更新2

如果您不关心数组成员的顺序,ES2015 + Set可能是比数据结构更好的数据结构Array.请参阅MDN有关如何实施isSupersetdifference使用危险的猴子修补的说明.

  • @Redu 猜测这取决于“相同成员”的含义 - 我认为它的意思是“具有相同的成员”。在我看来,`sameMembers([1,1,2],[2,1,2])`应该返回`true`。`sameMembersInOrder([1,1,2],[2,1,2])`又名`deepEquals([1,1,2],[2,1,2])`应该返回`false`。 (3认同)
  • 你的解决方案是错误的。“两个数组 arr1 和 arr2 具有相同的成员当且仅当:arr2 中的所有内容都在 arr1 中并且 arr1 中的所有内容都在 arr2 中”这也是错误的。这是一个数组而不是一个集合。所以`sameMembers([1,1,2],[2,1,2]);`应该返回false。 (2认同)

Mac*_*zyk 21

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;

}
Run Code Online (Sandbox Code Playgroud)

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

  • 排序需要 nlog(n) 时间。你不需要排序。这个答案 /sf/answers/3893026161/ 在线性时间内有效。 (6认同)
  • @canbax 当数组为 [1,2] 和 [1,1,2] 时,链接中的函数返回 true,在我的例子中,这是两个不同的数组。虽然这个函数对这两个不同的数组说假。 (2认同)

can*_*bax 14

我们的目标基本上是检查 2 个数组是否是相等的集合。set是数学定义的set。最快的排序渐近花费O(nlog(n))时间。因此,如果对数组进行排序,则至少需要O(nlog(n))时间。但是您可以更快地完成此任务,使用字典数据结构渐近地花费O(n)时间(平均情况不是最坏的情况)。在 JS 中,字典只是一个带有键和值的对象。

/** assumes array elements are primitive types
* check whether 2 arrays are equal sets.
* @param  {} a1 is an array
* @param  {} a2 is an array
*/
function areArraysEqualSets(a1, a2) {
  const superSet = {};
  for (const i of a1) {
    const e = i + typeof i;
    superSet[e] = 1;
  }

  for (const i of a2) {
    const e = i + typeof i;
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

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

  return true;
}
Run Code Online (Sandbox Code Playgroud)

请注意,此函数适用于原始类型的数组,并假定a1a2是数组。

  • 这不能处理其中一个数组中有重复值的情况。例如 `areArraysEqualSets([1, 2, 2], [1, 2])` (5认同)
  • 这不是问题的答案。这个问题不是问集合,而是问数组。[1,2,2] 和 [1,2] 不是相同的数组。该答案将被删除为“不是答案” (4认同)
  • @gman你错了,问题标题是“如何知道两个数组是否具有相同的值”。关于重复值并不是很清楚。但我知道他基本上是在问“两个数组是否是相等的集合”。所以我仍然认为我的答案是正确的,也是最快的工作算法。(我写完后没有检查新答案)。另外,请注意,我不是在谈论 javascript 中的 `Set` 类。我所说的设定是理论设定。这是一个数学定义。我已经给出了我所指内容的链接 (2认同)

小智 10

对于 ES6

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


let difference = array1.filter(x => !array2.includes(x));

console.log("equals", difference?.length != 0 ? false : true)
Run Code Online (Sandbox Code Playgroud)

  • 最好的直接答案在这里。 (2认同)

Ram*_*ngh 9

那这个呢?ES 2017 我想:

const array1 = [1, 3, 5];
const array2 = [1, 5, 3];

const isEqual = (array1.length === array2.length) && (array1.every(val => array2.includes(val)));
console.log(isEqual);
Run Code Online (Sandbox Code Playgroud)

第一个条件检查两个数组是否具有相同的长度,第二个条件检查第一个数组是否是第二个数组的子集。将这 2 个条件结合起来应该会导致对 2 个数组的所有项目进行比较,而不管元素的顺序如何。

上面的代码只有在两个数组都有非重复项时才有效。

  • 我认为如果 array1 有重复的条目,这会给出误报。在数组中,不保证不重复。在上面的示例中,如果数组 1 是“[1,1,5]”,它将返回 true。 (2认同)

San*_*eep 8

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

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

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