我有一个简单的JavaScript数组对象包含几个数字。

[267, 306, 108]

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


当前回答

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

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

5次运行100,000个索引的随机数数组的平均结果:

Reduce的运行时间为4.0392 ms Math.max.apply运行了3.3742毫秒 排序和获取第0个值花费了67.4724毫秒 数学。Max within reduce()运行了6.5804 ms 自定义findmax函数运行了1.6102 ms


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)

其他回答

应该很简单:

var countArray = [1,2,3,4,5,1,3,51,35,1,357,2,34,1,3,5,6];

var highestCount = 0;
for(var i=0; i<=countArray.length; i++){    
    if(countArray[i]>=highestCount){
    highestCount = countArray[i]
  }
}

console.log("Highest Count is " + highestCount);

您还可以扩展Array以拥有此函数,并使其成为每个数组的一部分。

Array.prototype.max = function(){return Math.max.apply( Math, this )};
myArray = [1,2,3];

console.log( myArray.max() );

最简单的语法,使用新的展开操作符:

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

来源:Mozilla MDN

几乎所有的答案都使用Math.max.apply(),这很好,但它有局限性。

函数参数被放置在堆栈上,这有一个缺点——限制。因此,如果你的数组大于限制,它将失败与RangeError:最大调用堆栈大小超过。

为了找到一个调用堆栈大小,我使用了下面的代码:

var ar = [];
for (var i = 1; i < 100*99999; i++) {
  ar.push(1);
  try {
    var max = Math.max.apply(Math, ar);
  } catch(e) {
    console.log('Limit reached: '+i+' error is: '+e);
    break;
  }
}

它在我的机器上的Firefox上是最大的——591519。这意味着如果数组包含超过591519个项,Math.max.apply()将导致RangeError。

这个问题的最佳解决方案是迭代方法(来源:https://developer.mozilla.org/):)

max = -Infinity, min = +Infinity;

for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] > max)
    max = numbers[i];
  if (numbers[i] < min)
    min = numbers[i];
}

我在我的博客上写过这个问题。

根据@Quasimondo的评论,这似乎被大部分人忽略了,下面的似乎有最好的表现,如下所示:https://jsperf.com/finding-maximum-element-in-an-array。请注意,虽然对于问题中的数组,性能可能没有显著影响,但对于大型数组,性能变得更重要,并且再次指出,如果数组长度超过65535,使用Math.max()甚至不起作用。看看这个答案。

function largestNum(arr) {
    var d = data;
    var m = d[d.length - 1];
    for (var i = d.length - 1; --i > -1;) {
      if (d[i] > m) m = d[i];
    }
    return m;
}