如何在JavaScript中比较两个数组?

3
如果我有两个数组作为参数,如何找到第二个参数作为子数组在第一个参数中出现的起始索引。
例如:[5,9,3,6,8],[3,6] 应返回2。
在JavaScript中是否有这样的函数,还是只需循环两者并进行比较?

没有这样的函数,你需要自己迭代和比较。 - Felix Kling
7个回答

4
findArrayInArray = function(a, b) {
    var ai = a.length
    ,   bi = b.length;
    for(var i=0; i<ai; i++) {
        if (a[i] === b[0]) {
            if(bi === 1) return i;
            for(var x=1; x<bi; x++) {
                if(a[i+x] === b[x]) {
                    if(x === bi-1) return i;
                } else {
                    break;
                }
            }
        }
    }
}

var arr1 = [5,9,3,6,8];
var arr2 = [3,6];

console.log(findArrayInArray(arr1,arr2)); // 2

http://jsfiddle.net/ymC8y/3/


似乎在这里无法通过一些测试用例:http://jsfiddle.net/jfriend00/uPwFU/。特别是,它似乎不能处理arr2.length == 1的情况。 - jfriend00
@jfriend00 谢谢,已经修复了,并进行了一些性能调整:http://jsperf.com/findsubarrayindex - StuR

1

直接回答你的问题,JS 中没有内置函数可以查找子数组。你需要进行一些类似于暴力循环搜索的操作,或者使用一些已经具备数组比较逻辑的外部库函数。以下是一个纯 JS 的暴力解决方案:

function findSubArrayIndex(master, sub) {
    for (var m = 0; m < master.length - sub.length + 1; m++) {
        for (var s = 0; s < sub.length; s++) {
            if (master[m + s] !== sub[s]) {
                break;
            } else if (s === sub.length - 1) {
                return m;
            }
        }
    }
    return -1;
}

工作演示:http://jsfiddle.net/jfriend00/mt8WG/


供参考,这里提供了一个性能优化过的函数版本:

function findSubArrayIndex(master, sub) {
    var subLen = sub.length, subFirst, m, mlen;

    if (subLen > 1) {
        subFirst = sub[0];
        for (m = 0, mlen = master.length - subLen + 1; m < mlen; m++) {
            if (master[m] === subFirst) {
                for (var s = 1; s < subLen; s++) {
                    if (master[m + s] !== sub[s]) {
                        break;
                    } else if (s === subLen - 1) {
                        return m;
                    }
                }
            }
        }
    } else if (subLen === 1) {
        subFirst = sub[0];
        for (m = 0, mlen = master.length; m < mlen; m++) {
            if (master[m] === subFirst) {
                return m;
            }
        }
    }
    return -1;
}

工作演示:http://jsfiddle.net/jfriend00/CGPtX/


@user2517028 - 我修改了我的回答措辞,以解释没有循环就没有内置的JS解决方案。我真的因为提供解决方案而应该被投反对票吗?此外,你的jQuery答案也只是在进行循环(它只是在jQuery函数内部)。 - jfriend00
1
@user2517028,我同意这确实不应该被踩。我给你点个赞。 - Samuel Neff
@user603007 - 运行了几个测试后,简化了答案并修复了一个边界情况问题。 - jfriend00
在 jsFiddle 上添加了一堆测试用例:http://jsfiddle.net/jfriend00/mt8WG/,以确保所有边界情况都得到正确处理。 - jfriend00
@jfriend00,为什么在你的第二个版本中,在“else if(subLen === 1)”时要循环主数组?你可以只做master.indexOf(sub [0])。或者更好的是,进行早期返回,像这样:http://jsfiddle.net/rd13/CGPtX/13/ - StuR
显示剩余5条评论

1
function index (a, b) {
    var as = new String(a),
        bs = new String(b),
        matchIndex = as.indexOf(bs);

    if (matchIndex === -1) {
        return -1;
    } else if (matchIndex === 0) {
        return 0;
    }
    return as.substring(0, matchIndex + 1).match(/,/g).length;
}

console.log(index([5,9,3,6,8], [3, 6]));

1
我最初考虑将其转换为字符串并使用正则表达式,但尽管它可以工作,但这种方式非常缓慢:http://jsperf.com/findarrayinarray - StuR
好的观点。如果性能是一个问题,那么可以使用“.split(',')”而不是正则表达式,这应该不会太慢。 - spirit walker
1
这似乎通过了这里的测试用例:http://jsfiddle.net/jfriend00/CJ77u/。如果第二个参数是一个空数组,它会返回`0` - 不确定该函数对于该情况应该返回什么。我的答案选择在第二个参数为零时返回-1,但我猜这并没有明确指定应该如何处理。 - jfriend00
@jfriend00,你是对的,它可能应该返回-1。 - spirit walker

1
你可以试试这个。
function compareArray(arr1, arr2){
  return arr1.join("") == arr2.join("");
}

这段代码在数组及其内容相同时返回true,如果数组及其内容不相同则返回false。

这并没有回答问题。 - Muhammad Khuzaima Umair

0
你可以通过将这个数组转换为字符串来使用JavaScript内置的String.indexOf方法。

function subArrIndex(arr, subArr) {
  let a1 = arr.join(" ");
  let a2 = subArr.join(" ")

  let index = a1.indexOf(a2);

  let subStringEarlier = a1.substr(0, index);

  // count number of spaces ' '
  return subStringEarlier.split(' ').length - 1;
}

let arr = [5,9,3,6,8]
let subArr= [3,6]

console.log(subArrIndex(arr, subArr));

P.S

如果数组中包含空格' ',它将无法工作。您可以使用其他分隔符,如,\n

0
let array1 = [11, 22, 33];
let array2 = [21, 22, 23];
let array3 = [11, 22, 33];

const compareArray = (a, b) => {
  return JSON.stringify(a) === JSON.stringify(b);
};

console.log(compareArrays(array1, array2));
console.log(compareArrays(array1, array3));

1
你应该添加解释。 - Super Kai - Kazuya Ito

-3

尝试这个 - 您遍历两个数组并比较每个元素:

var arr1 = [5,9,3,6,8];
var arr2 = [3,6];

findArrayInArray = function(arr1, arr2) {
  for(var i=0; i<arr1.length; i++) {
    for(var j=0; j<arr2.length; j++){
      if(arr1[i] === arr2[j]){
        return i;
      }
    }
  }
  return false;
}

findArrayInArray(arr1, arr2);

只有当 arr2.length == 1 时,此方法才有效,因为它不会比较 arr2 中第一个项以外的其他项。 - jfriend00
@jfriend00 我相信它会迭代遍历arr2中的每个项,除非找到与arr1[i]匹配的项。 - Huy
当您在此行中找到第一个匹配项 if(arr1[i] === arr2[j]){ 时,您的函数将返回。它不会比较 arr2 的其余部分。 - jfriend00
@jfriend00 这是因为他想要第一个匹配项的索引。如果我们已经有了一个匹配项,我们就不需要迭代函数的其余部分 - 至少这是我对他问题的理解。 - Huy
但是,它必须与arr2的所有项匹配,而不仅仅是arr2中的第一项。在此处查看其返回内容:http://jsfiddle.net/jfriend00/kLLrd/ - jfriend00

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