【问题标题】:Maximum call stack size exceeded with Math.min and Math.maxMath.min 和 Math.max 超出了最大调用堆栈大小
【发布时间】:2017-07-26 04:07:50
【问题描述】:

我有 js 函数来查找二维数组中的最小值和最大值,这在小数组上工作正常,但是当我将它传递给大数组时,它给了我range error

超过最大调用堆栈大小。

我使用的是最新版本的 Chrome。

function MaxMin2dray(arr, idx){
    return {
       min: Math.min.apply(null, arr.map(function (e) { return e[idx]})),
        max: Math.max.apply(null, arr.map(function (e) { return e[idx]}))
  }
}

【问题讨论】:

  • Function.prototype.apply 只能接收有限长度的数组作为其第二个参数。您应该手动找到最小值和最大值
  • 至少,你可以优化你的函数,去掉同一个数组上多余的 Array.prototype.map() 函数调用
  • 更准确的说:每个参数都占用栈空间,给任何函数传递太多参数都会导致栈溢出。
  • big array - 不错,chrome only 最多可以处理 125519 - 其他浏览器最多可以处理 4 倍

标签: javascript arrays


【解决方案1】:

Math.min & Math.max

Math.minMath.max 最有可能崩溃,或者为大数组返回 NaN (~10⁷)

(见@DavidWaters 和@EugeneGluhotorenko cmets)。

相反,您可以像这样使用旧的 javascript 循环:

(第二个函数要快得多)

function getMax(arr) {
    return arr.reduce((max, v) => max >= v ? max : v, -Infinity);
}

或者

function getMax(arr) {
    let len = arr.length;
    let max = -Infinity;

    while (len--) {
        max = arr[len] > max ? arr[len] : max;
    }
    return max;
}
  • 经过 1,000,000 项测试:
    第一个函数运行时间(在我的机器上)是 15.84 毫秒。第二个函数仅需 4.32 毫秒。

【讨论】:

  • 您是否有说明它们是递归操作的文档或代码参考?
  • @neverendingqs,这是一个公平的问题 :) 使用大数组时,我们会收到 Maximum call stack size exceeded 错误。这意味着堆栈大小比 JS 引擎可以处理的要大。当使用大量递归时,通常会发生这种类型的错误。如果您或其他任何人可以在 V8 代码中找到参考并提供更多实质性证据,那就更好了。
  • 查看当前代码chromium.googlesource.com/v8/v8/+/4.3.21/src/… Chrome 和 Javascript 内置的节点使用 for 循环来处理 Math.Max 和 Math.Min。自从提出问题以来,我没有查看这是否发生了变化,或者它是否与函数的调用方式有关。
  • 并非如此。这些函数不是递归的(参见上面评论中的 v8 源代码)。问题在于解构后的函数参数量。以下是有关堆栈如何工作的更多详细信息stackoverflow.com/a/53493938/438084
  • @EugeneGluhotorenko 和 DavidWaters 感谢您清除此问题。我更新了答案以反映您的发现 +1
【解决方案2】:
function minMax2DArray(arr, idx) {
    var max = -Number.MAX_VALUE,
        min = Number.MAX_VALUE;
    arr.forEach(function(e) {
        if (max < e[idx]) {
            max = e[idx];
        }
        if (min > e[idx]) {
           min = e[idx];
       }
    });
    return {max: max, min: min};
}

? 编辑:删除了MIN_VALUE 的使用(见下文)。

现代化版

const arrayMinMax = (arr) =>
  arr.reduce(([min, max], val) => [Math.min(min, val), Math.max(max, val)], [
    Number.POSITIVE_INFINITY,
    Number.NEGATIVE_INFINITY,
  ]);

【讨论】:

  • 很高兴它有所作为 :)
【解决方案3】:

bjornl 的回答有问题。根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_VALUE

MIN_VALUE 属性是最接近 0 的数字,而不是 JavaScript 可以表示的最负数。

更新后的代码:

function minMax2DArray(arr, idx) {
    var max = -Number.MAX_VALUE,
        min = Number.MAX_VALUE;
    arr.forEach(function(e) {
        if (max < e[idx]) {
            max = e[idx];
        }
        if (min > e[idx]) {
           min = e[idx];
       }
    });
    return {max: max, min: min};
}

【讨论】:

  • 感谢您指出这一点,罗伊!更新了我的答案以反映这一点。
猜你喜欢
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
  • 2020-11-19
  • 2013-08-23
  • 2021-09-07
  • 2017-11-12
  • 2015-03-15
相关资源
最近更新 更多