【问题标题】:Most efficient way to search for array in array of arrays在数组数组中搜索数组的最有效方法
【发布时间】:2021-10-08 13:44:24
【问题描述】:

我有一个大数组array1,其中填充了已经排序的数字数组,如下例所示。现在我想检查array1 是否包含array2

目前我有函数searchForArray 可以正常工作。但由于array1 的数组很大,所以速度很慢。

如何改进搜索功能以获得更好的性能?

var array1 = [
    [1, 0], [1, 2], [1, 5], [1 , 12],
    [2, 3], [2, 9], [2, 25],
    [7, 2], [7, 4], [7, 7], [7, 8], [7, 16],
    [8, 20], [8, 35], [8, 40], [8, 50]
];
var array2 = [7, 4];

if (searchForArray(array1, array2)) {
    // Array 2 is in array1
}


function searchForArray(bigArray, searchArray) {
    const a = JSON.stringify(bigArray);
    const b = JSON.stringify(searchArray);
    const c = a.indexOf(b);
    if (c != -1) {
        return true;
    }

    return false;
}

【问题讨论】:

  • 你的array1 总是有那种分类的性质吗?内部数组的第一个元素似乎已排序,您始终可以将其用于二进制搜索。
  • 这个问题有一个更好的位置:codereview.stackexchange.com,如果它被这里的社区否决
  • @SamridhTuladhar 是的,它在自然界中总是这样排序的。我将尝试实现二进制搜索来测试性能如何提高。
  • 它取决于您的数据大小、时间复杂度和空间复杂度的限制。对于像这样的小数据样本,线性搜索是首选,因为您不必花费额外的时间来对其进行排序。仅供参考:还有TreeMapHashMap
  • @HoangLe 我有非常大的数组,最多可容纳 20'000 个元素。数组中的数据已经自动排序如上图,所以我不必实现排序算法。

标签: javascript arrays sorting search


【解决方案1】:

这可能会更高效一些,因为您不需要 JSON.stringify 一个巨大的数组数组。只需查找与您要查找的数组具有相同元素的第一项。

function searchForArray(bigArray, searchArray) {
    return !!bigArray.find(item => item.join(',') === searchArray.join(','));
}

当然,这个速度取决于searchArraybigArray 中的位置。如果它在顶部,这是非常快的。如果在底部或根本不存在,如果searchArray 真的很大,这仍然需要一些时间。但至少这不会占用你所有的记忆。

【讨论】:

  • 感谢您的回复。不幸的是,这并没有提高我的表现。
【解决方案2】:

感谢所有回复或提出建议的人。

我现在实现了一个binary search 算法,它大大提高了我的性能(需要 110 秒的过程现在在

也许有人需要类似的东西:

function searchForArray(bigArray, searchArray) {
    var startIndex = 0;
    var endIndex = bigArray.length - 1;
    var startSearchIndex;
    var endSearchIndex;
    var firstIndexFound = false;

    while (startIndex <= endIndex) {
        var middle = Math.floor((startIndex + endIndex) / 2);

        if (bigArray[middle][0] === searchArray[0]) {
            // found the first key
            startIndex = middle;
            endIndex = middle;
            firstIndexFound = true;
            break;
        }
        else if (bigArray[middle][0] < searchArray[0]) {
            // continue searching to the right
            startIndex = middle + 1;
        }
        else {
            // search searching to the left
            endIndex = middle - 1;
        }
    }

    // Get index where to search for second key
    while (startIndex != 0 && bigArray[startIndex - 1][0] === searchArray[0]) {
        startIndex -= 1;
    }
    while (endIndex != bigArray.length - 1 && bigArray[endIndex + 1][0] === searchArray[0]) {
        endIndex += 1;
    }


    while (startIndex <= endIndex) {
        var middle = Math.floor((startIndex + endIndex) / 2);

        if (bigArray[middle][1] === searchArray[1]) {
            // found the second key
            return true;
        }
        else if (bigArray[middle][1] < searchArray[1]) {
            // continue searching to the right
            startIndex = middle + 1;
        }
        else {
            // search searching to the left
            endIndex = middle - 1;
        }
    }

    return false;
}

【讨论】:

  • 我强烈建议使用letconst 而不是var。这将确保变量保留在范围内,并且不会影响其余代码。
  • 也非常高兴看到需要 110 秒的东西减少到
  • 感谢您的意见,因为直到现在我还没有使用 javascript 进行太多工作,所以我通常使用 var 声明所有内容。我会检查letconst 的未来:)
【解决方案3】:

试试不带JSON.stringify()的检查:

function arraysEqual(a, b) {
    return a[0] === b[0] && a[1] === b[1]
}

function searchForArray(bigArray, searchArray) {
    return bigArray.some(a => arraysEqual(a, searchArray))
}

【讨论】:

  • 谢谢,我试一试,如果更快的话会告诉你
  • @StephanHäberle,我改变了答案,因为我的测试更快
猜你喜欢
  • 2016-08-14
  • 2014-04-11
  • 2015-01-01
  • 2020-03-20
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 2014-05-24
  • 2012-05-18
相关资源
最近更新 更多