我怎样才能轻松地获得一个JavaScript数组的最小或最大元素?

伪代码示例:

let array = [100, 0, 50]

array.min() //=> 0
array.max() //=> 100

当前回答

博士tl;

// For regular arrays:
var max = Math.max(...arrayOfNumbers);

// For arrays with tens of thousands of items:
let max = testArray[0];
for (let i = 1; i < testArrayLength; ++i) {
  if (testArray[i] > max) {
    max = testArray[i];
  }
}

MDN解决方案

关于Math.max()的官方MDN文档已经涵盖了这个问题:

下面的函数使用function .prototype.apply()来查找数值数组中的最大元素。getMaxOfArray([1,2,3])等价于Math。max(1,2,3),但是您可以在任何大小的编程构造数组上使用getMaxOfArray()。 函数getMaxOfArray(numArray) { Math.max返回。应用(null, numArray); } 或者使用新的展开运算符,获得数组的最大值变得容易得多。 Var arr = [1,2,3]; var max = Math.max(…arr);

数组的最大大小

根据MDN, apply和spread解决方案的限制为65536,这来自于参数的最大数量的限制:

But beware: in using apply this way, you run the risk of exceeding the JavaScript engine's argument length limit. The consequences of applying a function with too many arguments (think more than tens of thousands of arguments) vary across engines (JavaScriptCore has hard-coded argument limit of 65536), because the limit (indeed even the nature of any excessively-large-stack behavior) is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. To illustrate this latter case: if such an engine had a limit of four arguments (actual limits are of course significantly higher), it would be as if the arguments 5, 6, 2, 3 had been passed to apply in the examples above, rather than the full array.

他们甚至提供了一种混合解决方案,与其他解决方案相比,它的性能并不好。有关更多信息,请参阅下面的性能测试。

2019年的实际限制是调用堆栈的最大大小。对于现代基于Chromium的桌面浏览器,这意味着当使用apply或spread来查找min/max时,实际上只有数字的数组的最大大小是~120000。在此之上,将会出现堆栈溢出,并抛出以下错误:

RangeError:超过最大调用堆栈大小

使用下面的脚本(基于本文),通过捕获该错误,可以计算特定环境的限制。

警告!运行此脚本需要时间,并且根据您的系统性能,它可能会减慢或崩溃您的浏览器/系统!

let testArray = Array.from({length: 10000}, () => Math.floor(Math.random() * 2000000)); For (i = 10000;I < 1000000;+ + i) { testArray.push(Math.floor(Math.random() * 2000000)); 尝试{ Math.max。应用(null, testArray); } catch (e) { console.log(我); 打破; } }

大型阵列的性能

基于EscapeNetscape评论中的测试,我创建了一些基准测试,在一个只有100000项的随机数数组上测试5种不同的方法。

2019年的结果显示,标准循环(BTW没有大小限制)在任何地方都是最快的。apply和spread紧随其后,然后是MDN的混合解决方案,然后reduce是最慢的。

几乎所有的测试都给出了相同的结果,除了其中一个扩散somewhy的结果是最慢的。

如果你将你的数组增加到100万个项目,事情就会开始中断,你只剩下标准循环作为快速解决方案,而减少作为较慢的解决方案。

JSPerf基准

JSBen基准

JSBench。我的基准

基准测试源代码

var testArrayLength = 100000 var testArray = Array.from({length: testArrayLength}, () => Math.floor(Math.random() * 2000000)); // ES6 spread Math.min(...testArray); Math.max(...testArray); // reduce testArray.reduce(function(a, b) { return Math.max(a, b); }); testArray.reduce(function(a, b) { return Math.min(a, b); }); // apply Math.min.apply(Math, testArray); Math.max.apply(Math, testArray); // standard loop let max = testArray[0]; for (let i = 1; i < testArrayLength; ++i) { if (testArray[i] > max) { max = testArray[i]; } } let min = testArray[0]; for (let i = 1; i < testArrayLength; ++i) { if (testArray[i] < min) { min = testArray[i]; } } // MDN hibrid soltuion // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Using_apply_and_built-in_functions function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); min = Math.min(submin, min); } return min; } minOfArray(testArray); function maxOfArray(arr) { var max = -Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submax = Math.max.apply(null, arr.slice(i, Math.max(i + QUANTUM, len))); max = Math.max(submax, max); } return max; } maxOfArray(testArray);

其他回答

在这个时代(2022年),从数组中获得min + max的最有效方法是通过reduce在一次迭代中完成。

在JavaScript中:

const arr = [3, 0, -2, 5, 9, 4];

const i = arr.reduce((p, c) => {
    p.min = c < p.min ? c : p.min ?? c;
    p.max = c > p.max ? c : p.max ?? c;
    return p;
}, {min: undefined, max: undefined});

console.log(i); //=> { min: -2, max: 9 }

当输入没有数据时,它将输出{min: undefined, max: undefined}。

在TypeScript中,你只需要添加类型强制转换,所以返回类型被推断为{min: number, max: number},而不是{min: any, max: any}:

const arr = [3, 0, -2, 5, 9, 4];

const i = arr.reduce((p, c) => {
    p.min = c < p.min ? c : p.min ?? c;
    p.max = c > p.max ? c : p.max ?? c;
    return p;
}, {min: undefined as number, max: undefined as number});
//=> {min: number, max: number}

console.log(i); //=> { min: -2, max: 9 }

更新

在kiran goud注释之后,这里有一个使用数组而不是对象的替代方法:

const i = arr.reduce((p, c) => {
    p[0] = c < p[0] ? c : p[0] ?? c;
    p[1] = c > p[1] ? c : p[1] ?? c;
    return p;
}, [undefined, undefined]);

console.log(i); //=> [-2, 9]

如果你使用prototype.js框架,那么这段代码将正常工作:

arr.min();
arr.max();

这里有文档:max的Javascript原型框架

还有一种方法:

var arrayMax = Function.prototype.apply.bind(Math.max, null);

用法:

var max = arrayMax([2, 5, 1]);

我是这样解决问题的:

    var strDiv  = "4,8,5,1"
var arrayDivs   = strDiv.split(",")
var str = "";

for (i=0;i<arrayDivs.length;i++)
{
    if (i<arrayDivs.length-1)
    {
      str = str + eval('arrayDivs['+i+']')+',';
    } 
    else if (i==arrayDivs.length-1)
    {
      str = str + eval('arrayDivs['+i+']');
    }
}

str = 'Math.max(' + str + ')';
    var numMax = eval(str);

我希望我能帮上忙。

致以最亲切的问候。

下面的脚本在ndoejs中为我工作:

 var numbers = [1, 2, 3, 4];
 console.log('Value:: ' + Math.max.apply(null, numbers) ); // 4