我怎样才能轻松地获得一个JavaScript数组的最小或最大元素?
伪代码示例:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
我怎样才能轻松地获得一个JavaScript数组的最小或最大元素?
伪代码示例:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
当前回答
这里有很多不错的答案,下面是一个typescript版本,可以处理一些值未定义的列表。
如何使用:
const testDates = [
undefined,
new Date('July 30, 1986'),
new Date('July 31, 1986'),
new Date('August 1, 1986'),
]
const max: Date|undefined = arrayMax(testDates); // Fri Aug 01 1986
const min: Date|undefined = arrayMin(testDates); // Min: Wed Jul 30 1986
const test: Date = arrayMin(testDates); // Static type error
const anotherTest: undefined = arrayMin(testDates); // Static type error
定义(notEmpty定义来自这篇文章):
function arrayMax<T>(values?: (T | null | undefined)[]): T | undefined {
const nonEmptyValues = filterEmpty(values);
if (nonEmptyValues.length === 0) {
return undefined;
}
return nonEmptyValues.reduce((a, b) => (a >= b ? a : b), nonEmptyValues[0]);
}
function arrayMin<T>(values?: (T | null | undefined)[]): T | undefined {
const nonEmptyValues = filterEmpty(values);
if (nonEmptyValues.length === 0) {
return undefined;
}
return nonEmptyValues.reduce((a, b) => (a <= b ? a : b), nonEmptyValues[0]);
}
function filterEmpty<T>(values?: (T | null | undefined)[] | null): T[] {
return values?.filter(notEmpty) ?? [];
}
function notEmpty<T>(value: T | null | undefined): value is T {
if (value === null || value === undefined) return false;
const testDummy: T = value;
return true;
}
我没有使用数学。max函数,正如文档中建议的那样,因为这样我就可以将这个函数与任何可比对象一起使用(如果你知道如何键入它,请告诉我,这样我就可以更好地定义T)。
其他回答
博士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);
下面是一种从对象数组中获取最大值的方法。创建一个副本(使用切片),然后按降序对副本排序并抓取第一项。
var myArray = [
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
maxsort = myArray.slice(0).sort(function(a, b) { return b.ID - a.ID })[0].ID;
你可以使用数组。排序,但你必须写一个简单的数字排序函数,因为默认是字母排序。
看例2。
然后你可以得到arr[0]和arr[arr。长度-1]来得到最小值和最大值。
插入以逗号分隔的数字,然后单击要调用的事件,即获取最大或最小数字。
function maximumNumber() { var numberValue = document.myForm.number.value.split(","); var numberArray = []; for (var i = 0, len = numberValue.length; i < len; i += 1) { numberArray.push(+numberValue[i]); var largestNumber = numberArray.reduce(function (x, y) { return (x > y) ? x : y; }); } document.getElementById("numberOutput").value = largestNumber; } function minimumNumber() { var numberValue = document.myForm.number.value.split(","); var numberArray = []; for (var i = 0, len = numberValue.length; i < len; i += 1) { numberArray.push(+numberValue[i]); var smallestNumber = numberArray.reduce(function (x, y) { return (x < y) ? x : y; }); } document.getElementById("numberOutput").value = smallestNumber; } function restrictCharacters(evt) { evt = (evt) ? evt : window.event; var charCode = (evt.which) ? evt.which : evt.keyCode; if (((charCode >= '48') && (charCode <= '57')) || (charCode == '44')) { return true; } else { return false; } } <div> <form name="myForm"> <table> <tr> <td>Insert Number</td> <td><input type="text" name="number" id="number" onkeypress="return restrictCharacters(event);" /></td> <td><input type="button" value="Maximum" onclick="maximumNumber();" /></td> <td><input type="button" value="Minimum" onclick="minimumNumber();"/></td> <td><input type="text" id="numberOutput" name="numberOutput" /></td> </tr> </table> </form> </div>
如果你需要性能,那么对于小数组来说这是最好的方法:
var min = 99999;
var max = 0;
for(var i = 0; i < v.length; i++)
{
if(v[i] < min)
{
min = v[i];
}
if(v[i] >= max)
{
max = v[i];
}
}