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

伪代码示例:

let array = [100, 0, 50]

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

当前回答

如果你使用sugar.js库,你可以按照你的建议编写arr.min()和arr.max()。您还可以从非数值数组中获得最小值和最大值。

min(map, all = false)返回数组中包含 最小值。Map可以是映射要检查的值的函数或 作为快捷键的字符串。如果全部为真,将返回所有的min 数组中的值。 max(map, all = false)返回数组中带有 最大的价值。Map可以是映射要检查的值的函数 或者是作为快捷键的字符串。如果all为true,将返回all max 数组中的值。

例子:

[1,2,3].min() == 1
['fee','fo','fum'].min('length') == "fo"
['fee','fo','fum'].min('length', true) == ["fo"]
['fee','fo','fum'].min(function(n) { return n.length; }); == "fo"
[{a:3,a:2}].min(function(n) { return n['a']; }) == {"a":2}
['fee','fo','fum'].max('length', true) == ["fee","fum"]

像Lo-Dash和underscore.js这样的库也提供了类似强大的min和max函数:

例子来自《Lo-Dash》:

_.max([4, 2, 8, 6]) == 8
var characters = [
  { 'name': 'barney', 'age': 36 },
  { 'name': 'fred',   'age': 40 }
];
_.max(characters, function(chr) { return chr.age; }) == { 'name': 'fred', 'age': 40 }

其他回答

对于一个简洁的现代解决方案,可以对数组执行reduce操作,跟踪当前的最小值和最大值,因此数组只迭代一次(这是最优的)。为了简洁起见,这里使用了解构赋值。

Let array = [100, 0, 50]; Let [min, max] =数组。减少(((prevMin prevMax],咕咕叫)= > (数学。min(prevMin, curr),数学。max(prevMax, curr)],[∞,-∞]); console.log(“分钟:分钟); console.log(“马克斯:Max);

为了只找到最小值或最大值,我们可以以大致相同的方式使用执行reduce操作,但我们只需要跟踪之前的最优值。这种方法比使用apply更好,因为当数组对堆栈来说太大时,它不会导致错误。

Const arr = [- 1,9,3, - 6,35]; //只找到最小值 const min = arr.reduce((a,b)=>Math.min(a,b),无穷大); console.log(“分钟:Min); / / 6 //只找到最大值 const max = arr.reduce((a,b)=>Math.max(a,b), -无穷大); console.log(“马克斯:Max); / / 35

博士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);

array.sort((a, b) => b - a)[0];

给出数字数组中的最大值。

array.sort((a, b) => a - b)[0];

给出一组数字中的最小值。

Let array = [0,20,45,85,41,5,7,85,90,111]; 令maximum = array。排序((a, b) => b - a)[0]; 令minimum = array。排序((a, b) => a - b)[0]; console.log(最小值,最大值)

还有一种方法:

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

用法:

var max = arrayMax([2, 5, 1]);
var max_of_array = Math.max.apply(Math, array);

完整的讨论见: http://aaroncrane.co.uk/2008/11/javascript_max_api/