在 JavaScript 中检查一个数组是否包含另一个数组

4
JavaScript 的 includes 函数可用于查找数组中是否存在某个元素。看下面的例子:

var arr = ['hello', 2, 4, [1, 2]];

console.log( arr.includes('hello') );
console.log( arr.includes(2) );

console.log( arr.includes(3) );

console.log( arr.includes([1, 2]) );

'hello'或者2传递给该函数,会返回true,因为它们都存在于数组arr中。

3传递给该函数,会返回false,因为它在数组中不存在。

然而,为什么arr.includes([1, 2])也会返回false,即使这和数组中的最后一个元素相等呢?如果这种方法不起作用,那么我如何找到我的数组是否包含项[1, 2]呢?


1
这个回答解决了你的问题吗?如何在数组中查找特定的数组? - Sebastian Simon
3
我同意这是个重复的问题,但我认为这个问题和答案更好。 - dwjohnston
3个回答

3
Array#includes检查浅层比较,因此在您的情况下,字符串和数字是原语,只有一个实例,因此您从Array#includes获得true

但是当您检查数组时,您正在传递一个新的数组实例,它不是您要检查的数组中的同一实例,因此浅层比较失败。

要检查是否包含一个数组在另一个数组中,请先检查它是否为数组,然后在数组之间进行深度比较。

  • 请注意,下面的代码片段仅适用于原始数组

var arr = ['hello', 2, 4, [1, 2]];
const includesArray = (data, arr) => {
  return data.some(e => Array.isArray(e) && e.every((o, i) => Object.is(arr[i], o)));
}

console.log(includesArray(arr, [1, 2]));

但是,如果您保留对数组[1, 2]的引用并使用该引用进行搜索,则Array#includes将按照浅层比较的方式正常工作(遵守same value zero algorithm):

const child =  [1, 2];
const arr = ['hello', 2, 4, child];

console.log(arr.includes(child));


刚刚发现了includesArray算法中的一个错误,例如console.log(includesArray(arr, [1, 2, 3]));返回true而不是false。数组[1, 2, 3]arr中并不存在,但却被找到了。 - abulka

3

.includes() 方法使用sameValueZero相等算法来确定数组中是否存在元素。

当比较的两个值不是数字时,sameValueZero 算法会使用SameValueNonNumber 算法。该算法由8个步骤组成,最后一步与您的代码相关,即当两个对象进行比较时。这一步是:

  1. 如果 x 和 y 是相同的 Object 值,则返回 true。否则,返回 false。

因此,在对象的情况下,SameValueZero 算法仅在两个对象是完全相同 时返回 true。

在您的代码中,由于 arr 数组内的 [1, 2] 与您传递给 .includes() 方法的 [1, 2] 不是完全相同的,所以 .includes() 方法找不到数组内的对应元素,结果返回 false


1

如果您不介意使用 lodash,这个算法是准确的 - 而不像被接受的答案。

import _ from 'lodash';

export const includesArray = (haystack, needle) => {
    for (let arr of haystack)
        if (_.isEqual(arr, needle)) {
            return true
    }
    return false
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接