我如何找到 JavaScript 数组中包含的最大数字?

IT技术 javascript algorithm arrays max
2021-01-10 23:43:28

我有一个简单的 JavaScript Array 对象,其中包含一些数字。

[267, 306, 108]

有没有一个函数可以找到这个数组中的最大数?

6个回答

辞职救援:

Array.max = function( array ){
    return Math.max.apply( Math, array );
};

警告:由于某些 VM 上的最大参数数低至 65535,如果您不确定数组是否那么小,请使用 for 循环。

FWIW,如果性能是一个因素在您的解决方案,我会测试相比,你自己轻松编码的功能,以确保它运行良好。我们倾向于假设本机实现会更快;事实上,apply通话费用可以很容易地消除这种情况。
2021-03-25 23:43:28
啊,但现在它以稍微弯曲的方式贴在它上面SO 质量贴纸
2021-03-29 23:43:28
此外,这种方法并不稳健。如果您的数组大于导致的最大堆栈大小,则失败RangeError: Maximum call stack size exceeded.
2021-04-02 23:43:28
@CrescentFresh 根据这个:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...它被硬编码为 65535。根据这个:code.google.com/p/v8/issues/detail?id =172并且根据参数被压入堆栈的知识我们知道它不是无限的
2021-04-03 23:43:28
如果我的数组长度大于参数计数限制怎么办?
2021-04-07 23:43:28

您可以使用 apply 函数来调用Math.max

var array = [267, 306, 108];
var largest = Math.max.apply(Math, array); // 306

它是如何工作的?

应用功能用于调用另一个函数,与给定的上下文中和参数,作为数组提供。min 和 max 函数可以接受任意数量的输入参数: Math.max(val1, val2, ..., valN)

所以如果我们调用:

Math.min.apply(Math, [1, 2, 3, 4]);

apply 函数将执行:

Math.min(1, 2, 3, 4);

请注意,第一个参数上下文对这些函数并不重要,因为它们是静态的。无论传递的上下文是什么,它们都将起作用。

我比其他人更喜欢这个答案,因为它解释了一切的作用以及原因。+1
2021-03-18 23:43:28
那太棒了。但是如果我的数组长度超过参数大小限制(函数)怎么办?然后怎样呢 ?
2021-04-06 23:43:28
哇,你费了很大力气才给出答案:D
2021-04-08 23:43:28

最简单的语法,使用新的扩展运算符

var arr = [1, 2, 3];
var max = Math.max(...arr);

来源:Mozilla MDN

但是,如果数组元素过多, spread (...) 和 apply 要么失败要么返回错误的结果 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-03-11 23:43:28
@Green FWIW,参数计数限制为 65536(至少在 Chrome 上)([source(bugs.webkit.org/show_bug.cgi?id=80797)])。因此,如果您的数组有超过 65536 个元素,则此答案将不起作用。
2021-03-29 23:43:28
65536 应该对任何人都足够了
2021-04-09 23:43:28

我不是 JavaScript 专家,但我想看看这些方法是如何叠加的,所以这对我来说是一个很好的实践。我不知道这在技术上是否是对这些进行性能测试的正确方法,但我只是一个接一个地运行它们,正如您在我的代码中看到的那样。

排序并获取第 0 个值是迄今为止最糟糕的方法(它会修改数组的顺序,这可能是不可取的)。对于其他人,除非您谈论的是数百万个索引,否则差异可以忽略不计。

使用 100,000 索引的随机数数组运行五次的平均结果:

  • reduce运行耗时4.0392 毫秒
  • Math.max.apply运行耗时3.3742 毫秒
  • 排序并获取第 0 个值需要67.4724 毫秒才能运行
  • reduce() 中的 Math.max运行耗时6.5804 毫秒
  • 自定义 findmax 函数运行耗时1.6102 毫秒

var performance = window.performance

function findmax(array)
{
    var max = 0,
        a = array.length,
        counter

    for (counter=0; counter<a; counter++)
    {
        if (array[counter] > max)
        {
            max = array[counter]
        }
    }
    return max
}

function findBiggestNumber(num) {
  var counts = []
  var i
  for (i = 0; i < num; i++) {
      counts.push(Math.random())
  }

  var a, b

  a = performance.now()
  var biggest = counts.reduce(function(highest, count) {
        return highest > count ? highest : count
      }, 0)
  b = performance.now()
  console.log('reduce took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest2 = Math.max.apply(Math, counts)
  b = performance.now()
  console.log('Math.max.apply took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest3 = counts.sort(function(a,b) {return b-a;})[0]
  b = performance.now()
  console.log('sorting and getting the 0th value took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest4 = counts.reduce(function(highest, count) {
        return Math.max(highest, count)
      }, 0)
  b = performance.now()
  console.log('Math.max within reduce() took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest5 = findmax(counts)
  b = performance.now()
  console.log('custom findmax function took ' + (b - a) + ' ms to run')
  console.log(biggest + '-' + biggest2 + '-' + biggest3 + '-' + biggest4 + '-' + biggest5)

}

findBiggestNumber(1E5)
对我来说,这是这个问题的最佳答案。
2021-04-08 23:43:28
我已经jsperf tests为上述
2021-04-09 23:43:28

我发现对于更大的数组(~100k 个元素),用一个简单的循环简单地迭代数组实际上是值得的for,比执行 ~30% Math.max.apply()

function mymax(a)
{
    var m = -Infinity, i = 0, n = a.length;

    for (; i != n; ++i) {
        if (a[i] > m) {
            m = a[i];
        }
    }

    return m;
}

基准测试结果

FWIW,现在在 Chrome 31 上达到 84%。
2021-04-02 23:43:28