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


Answers:


315

进行救援:

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

警告:由于某些VM的最大参数个数低至65535,因此,如果不确定数组的大小,请使用for循环。


15
嗯,但是现在它以一种稍微弯曲的方式贴上了质量SO标签
Shog9年

2
FWIW,如果性能是一个因素在您的解决方案,我会测试相比,你自己轻松编码的功能,以确保它运行良好。我们倾向于假设本地实现会更快。实际上,apply通话费用可以很轻松地将其清除。
TJ Crowder

2
如果我的数组长度大于参数计数限制怎么办?
lukas.pukenis 2013年

3
@CrescentFresh根据此代码:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…硬编码为65535。根据此代码:code.google.com/p/v8/issues/detail?id = 172,并且知道参数已被压入堆栈,我们知道它不是无限的
lukas.pukenis

9
而且,该方法也不可靠。如果您的数组大于堆栈的最大大小,它将失败,从而导致RangeError: Maximum call stack size exceeded.
Mark Lundin

197

您可以使用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);

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


2
哇,您付出了很多努力:D
ShrekOverflow 2012年

1
那很棒。但是,如果我的数组长度超过参数的大小限制(函数),该怎么办?然后怎样呢 ?
lukas.pukenis 2013年

1
与其他答案相比,我更喜欢此答案,因为它说明了所有功能以及原因。+1
马文(Marvin)

59

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

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

资料来源:Mozilla MDN


2
然而,这两种传播(...),并应用要么失败或返回错误的结果,如果数组有太多元素 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
格林

@Green FWIW,参数计数限制为65536(至少在Chrome上为)([source(bugs.webkit.org/show_bug.cgi?id=80797)])。因此,如果您的数组包含65536个以上的元素,则此答案将无效。
mgthomas99 '18 -4-6

4
65536应该足以满足任何人
vsync

41

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

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

五次运行的平均结果,其中包含100,000个索引的随机数数组:

  • 减少花费4.0392ms运行
  • Math.max.apply花了3.3742ms运行
  • 排序并获得第0个值了67.4724ms运行
  • reduce()中的Math.max 运行需要6.5804ms
  • 自定义findmax函数耗时1.6102ms运行

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)

7
对我来说,这是此问题的最佳答案。
rzelek

1
我已经做到jsperf tests
vsync

37

我发现,对于更大的数组(〜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;
}

基准结果


3
FWIW,现在出来,以84%的铬31
宜兰比亚瓦

31

您可以按降序对数组进行排序并获得第一项:

[267, 306, 108].sort(function(a,b){return b-a;})[0]

4
我想您也可以排序并获取最后一个项目...?
Shog9年

@ Shog9:是的,但是您需要自己指定比较功能:sort(function(a,b){return b-a;})
Gumbo

9
啊。我当时想的更像是:[...].sort().pop()
Shog9年

4
“发现的数量取N阶,排序顺序需要之间(N log n)的,以级数(n的平方),dependig上的排序算法中使用的” - webmasterworld.com/forum91/382.htm
马可Luglio

2
还请记住,这会对数组进行排序,这可能是也可能不是预期的副作用。应用解决方案性能更好,并且没有副作用。
Caleb

28

这个怎么样:

var arr = [1,2,3,4];

var largest = arr.reduce(function(x,y){
       return (x > y) ? x : y;
});

console.log(largest);

如果我首先看到此答案(当前在列表的底部),我将节省两个小时。
user139301 2015年

1
Math.max方法可能是最标准的方法,但是当数组太大(500K)时,我得到了堆栈溢出。这个答案快速有效,是我最终自己使用的答案,因此我对此表示赞同。
周杰伦

8

如何使用Array.reduce

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});

初始值应设置为-Infinity
杰克

@Jack,为什么需要这个?即使使用所有负数组成的数组,我也可以获得有效的结果。
CodeToad 2014年

1
这是边缘情况,数组为空。
杰克

5

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

函数参数放置在堆栈上,该堆栈有一个缺点-限制。因此,如果您的数组大于限制,它将失败RangeError: Maximum call stack size exceeded.

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

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];
}

我已经在这里的博客上写了关于这个问题的文章。


1
这不公平。我想在这里就这样给出答案,而不是另一个指向第三方资源的链接。尤其是当它与“这里的一切都很糟糕,但是快来看,它对我的​​博客如此好...”相结合
osa

@SergeyOrshanskiy与第三方的链接非常有效,以防它被新的信息和解决方案更新。也无需感到冒犯。人们也只想解决您的问题。我也想解决它,所以我在博客上写了它
lukas.pukenis


5

通过手动方式轻松找到最大值和最小值。这段代码比Math.max.apply; 我已经尝试了多达1000k数组中的数字。

function findmax(array)
{
    var max = 0;
    var a = array.length;
    for (counter=0;counter<a;counter++)
    {
        if (array[counter] > max)
        {
            max = array[counter];
        }
    }
    return max;
}

function findmin(array)
{
    var min = array[0];
    var a = array.length;
    for (counter=0;counter<a;counter++)
    {
        if (array[counter] < min)
        {
            min = array[counter];
        }
    }
    return min;
}

findmax()如果数组中只有负数,则给出错误的结果;findmin()为空数组给出错误的结果。
杰克




1

不要忘记可以使用自动换行功能Function.prototype.bind,为您提供“全天然” 功能

var aMax = Math.max.apply.bind(Math.max, Math);
aMax([1, 2, 3, 4, 5]); // 5

1

您也可以扩展Array为具有此功能,并使它成为每个数组的一部分。

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

console.log( myArray.max() );

1
效率极低。
Frank Schmitt 2014年

@FrankSchmitt,谢谢,我同意。原始答案不是一个好的解决方案。默认情况下,排序不对数字排序,而是将元素视为字符串。编辑我的答案以进行正确排序。
Izz

那不是我的意思。对数组进行排序以查找最大值本质上效率很低,因为它至少需要进行N个log N次运算,而查找最大值可以在N次操作中完成。
Frank Schmitt 2014年

1

您也可以使用forEach

var maximum = Number.MIN_SAFE_INTEGER;

var array = [-3, -2, 217, 9, -8, 46];
array.forEach(function(value){
  if(value > maximum) {
    maximum = value;
  }
});

console.log(maximum); // 217


1

使用- Array.prototype.reduce()很酷!

[267, 306, 108].reduce((acc,val)=> (acc>val)?acc:val)

其中acc =累加器val =当前值 ;

var a = [267, 306, 108].reduce((acc,val)=> (acc>val)?acc:val);

console.log(a);


1

你可以试试看

var arr = [267,306,108];
var largestNum = 0;
for(i=0;i<arr.length;i++) {
   if(arr[i]>largest){
    var largest = arr[i];
   }
}
console.log(largest);

1

我刚开始使用JS,但是我认为这种方法会很好:

var array = [34, 23, 57, 983, 198];<br>
var score = 0;

for(var i = 0; i = array.length; i++) {
  if(array[ i ] > score) {
    score = array[i];
  }
}

如果array仅包含负数,将有麻烦。
Teepeemm

0

在多维数组中找到最大的数

var max = []; 

for(var i=0; arr.length>i; i++ ){

   var arra = arr[i];
   var largest = Math.max.apply(Math, arra);
   max.push(largest);

   }
return max;

始终建议在代码中添加一些详尽的解释,尤其是在已经存在多个其他答案的情况下。为什么这与众不同/更好?
Bowdzone

@Bowdzone,感谢您的评论。这种方法是非常基本的,因此只需很少的一些方法知识就可以轻松理解。
Liveindream

这不会返回最大数,而是返回多维数组中每个数组中最大数的数组。您可能需要添加例如var tmax = Math.max.apply(Math, max),或者更好的方法,例如在stackoverflow.com/a/54980012/7438857中使用循环功能的闭包。进行此修改后,最好回答一个单独的问题,即如何“在多维数组中找到最大的数字”,或在stackoverflow.com/questions/32616910/…上回答。在制品:jsfiddle.net/jamesray/3cLu9for/8
詹姆斯·雷

stackoverflow.com/a/32617019/7438857是正确问题的更好答案,尽管此答案不能回答上述问题,但它会返回多维数组中每个数组中的最大数字。
James Ray

0

运行这个:

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

现在尝试[3,10,2].max()返回10


0

使用冒泡排序查找最大值和最小值

    var arr = [267, 306, 108];

    for(i=0, k=0; i<arr.length; i++) {
      for(j=0; j<i; j++) {
        if(arr[i]>arr[j]) {
          k = arr[i];
          arr[i] = arr[j];
          arr[j] = k;
        }
      }
    }
    console.log('largest Number: '+ arr[0]);
    console.log('Smallest Number: '+ arr[arr.length-1]);


1
(1)Javascript数组已经具有O(n log n)排序功能。(2)冒泡排序为O(n ^ 2)。(3)求出最小值和最大值为O(n)。
Teepeemm,

0

试试这个

function largestNum(arr) {
  var currentLongest = arr[0]

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

  return currentLongest
}

1
这个答案与本页上的其他答案有本质区别吗?
Teepeemm

0

根据@Quasimondo的评论(似乎已被广泛忽略),以下内容似乎具有最佳性能,如下所示:https : //jsperf.com/finding-maximum-element-in-an-array。请注意,虽然对于问题中的阵列,性能可能不会产生重大影响,但对于大型阵列而言,性能变得更为重要,并且再次指出,Math.max()如果阵列长度大于65535,则使用甚至都不起作用。另请参见此答案

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;
}

0

使用三元运算符的递归方法

const findMax = (arr, max, i) => arr.length === i ? max :
  findMax(arr, arr[i] > max ? arr[i] : max, ++i)

const arr = [5, 34, 2, 1, 6, 7, 9, 3];
const max = findMax(arr, arr[0], 0)
console.log(max);


0

for/of回路解决方案:

const numbers = [2, 4, 6, 8, 80, 56, 10];


const findMax = (...numbers) => {
  let currentMax = numbers[0]; // 2

  for (const number of numbers) {
    if (number > currentMax) {
      console.log(number, currentMax);
      currentMax = number;
    }
  }
  console.log('Largest ', currentMax);
  return currentMax;
};

findMax(...numbers);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.