在JavaScript中查找数组的最小/最大元素
如何轻松获得JavaScript数组的最小或最大元素?
示例伪代码:
let array = [100, 0, 50] array.min() //=> 0 array.max() //=> 100
如何增加内置的数组对象来使用Math.max
/ Math.min
来代替:
Array.prototype.max = function() { return Math.max.apply(null, this); }; Array.prototype.min = function() { return Math.min.apply(null, this); };
这是一个JSFiddle 。
增加内build插件可能会导致与其他库(有些人会看到)发生冲突,所以您可能会更习惯于直接apply
Math.xxx()
应用于您的数组:
var min = Math.min.apply(null, arr), max = Math.max.apply(null, arr);
或者,假设您的浏览器支持ECMAScript 6,则可以使用与apply
方法类似的spread运算符 :
var min = Math.min( ...arr ), max = Math.max( ...arr );
var max_of_array = Math.max.apply(Math, array);
有关完整的讨论,请参阅: http : //aaroncrane.co.uk/2008/11/javascript_max_api/
对于大数组(〜10个元素), Math.min
和Math.max
在Node.js中都会产生以下错误。
RangeError:超出最大调用堆栈大小
更可靠的解决scheme是不将每个元素添加到调用堆栈,而是传递一个数组:
function arrayMin(arr) { return arr.reduce(function (p, v) { return ( p < v ? p : v ); }); } function arrayMax(arr) { return arr.reduce(function (p, v) { return ( p > v ? p : v ); }); }
如果你关心速度,下面的代码比我的电脑上的Math.max.apply
快3倍。 请参阅http://jsperf.com/min-and-max-in-array/2 。
function arrayMin(arr) { var len = arr.length, min = Infinity; while (len--) { if (arr[len] < min) { min = arr[len]; } } return min; }; function arrayMax(arr) { var len = arr.length, max = -Infinity; while (len--) { if (arr[len] > max) { max = arr[len]; } } return max; };
如果您的数组包含string而不是数字,则还需要将其强制转换为数字。 下面的代码就是这样做的,但是它会在我的机器上减慢〜10倍的代码速度。 请参阅http://jsperf.com/min-and-max-in-array/3 。
function arrayMin(arr) { var len = arr.length, min = Infinity; while (len--) { if (Number(arr[len]) < min) { min = Number(arr[len]); } } return min; }; function arrayMax(arr) { var len = arr.length, max = -Infinity; while (len--) { if (Number(arr[len]) > max) { max = Number(arr[len]); } } return max; };
使用扩展运算符(ES6)
Math.max(...array); // the same with "min" => Math.min(...array);
const array = [10, 2, 33, 4, 5]; console.log( Math.max(...array) )
如果你像我一样偏执使用Math.max.apply
( 根据MDN给出大数组可能会导致错误),请尝试以下操作:
function arrayMax(array) { return array.reduce(function(a, b) { return Math.max(a, b); }); } function arrayMin(array) { return array.reduce(function(a, b) { return Math.min(a, b); }); }
或者,在ES6中:
function arrayMax(array) { return array.reduce((a, b) => Math.max(a, b)); } function arrayMin(array) { return array.reduce((a, b) => Math.min(a, b)); }
匿名函数是不幸的必要的(而不是使用Math.max.bind(Math)
因为reduce
不只是传递a
和b
的function,而且i
和一个参考数组本身,所以我们必须确保我们不要也不要试图打电话给这些人。
.apply
程序通常用于当用参数值列表调用可变参数时
Math.max([value1[,value2, ...]])
函数返回零个或多个数字中最大的一个。
Math.max(10, 20); // 20 Math.max(-10, -20); // -10 Math.max(-10, 20); // 20
Math.max()
方法不允许您传入数组。 如果你有一个你需要得到最大值的列表,你通常会使用Function.prototype.apply()来调用这个函数,例如
Math.max.apply(null, [10, 20]); // 20 Math.max.apply(null, [-10, -20]); // -10 Math.max.apply(null, [-10, 20]); // 20
但是,从ECMAScript 6开始,您可以使用扩展运算符 :
扩展运算符允许在需要多个参数(用于函数调用)或多个元素(用于数组文字)的地方扩展expression式。
使用扩展运算符,上面的可以被重写为:
Math.max(...[10, 20]); // 20 Math.max(...[-10, -20]); // -10 Math.max(...[-10, 20]); // 20
当使用可变参数调用函数时,您甚至可以添加其他值,例如
Math.max(...[10, 20], 50); // 50 Math.max(...[-10, -20], 50); // 50
奖金:
Spread操作符使您能够使用数组文本语法来创build新的数组,在ES5中,您需要使用push
, splice
等组合来回退到命令式代码。
let foo = ['b', 'c']; let bar = ['a', ...foo, 'd', 'e']; // ['a', 'b', 'c', 'd', 'e']
TL;博士
var max = Math.max(...arrayOfNumbers);
官方的Math.max()
MDN文档
以下函数使用Function.prototype.apply()来查找数字数组中的最大元素。
getMaxOfArray([1, 2, 3])
等价于Math.max(1, 2, 3)
,但是可以使用getMaxOfArray()
构造任意大小的数组。function getMaxOfArray(numArray) { return Math.max.apply(null, numArray); }
或者用新的扩展运算符 ,获得数组的最大值变得更容易。
var arr = [1, 2, 3]; var max = Math.max(...arr);
你可以通过扩展数组types来实现:
Array.max = function( array ){ return Math.max.apply( Math, array ); }; Array.min = function( array ){ return Math.min.apply( Math, array ); };
从这里加强(John Resig)
其他人已经提供了一些解决scheme,他们增加了Array.prototype
。 我想在这个答案是澄清是否应Math.min.apply( Math, array )
或Math.min.apply( null, array )
。 那么应该使用什么上下文, Math
还是null
?
当将null
作为上下文apply
,上下文将默认为全局对象(在浏览器的情况下为window
对象)。 传递Math
对象作为上下文将是正确的解决scheme,但它也不会伤害传递null
。 在装饰Math.max
函数时,下面是一个null
可能会导致麻烦的例子:
// decorate Math.max (function (oldMax) { Math.max = function () { this.foo(); // call Math.foo, or at least that's what we want return oldMax.apply(this, arguments); }; })(Math.max); Math.foo = function () { print("foo"); }; Array.prototype.max = function() { return Math.max.apply(null, this); // <-- passing null as the context }; var max = [1, 2, 3].max(); print(max);
以上将抛出一个exception,因为this.foo
将被评估为window.foo
,这是undefined
。 如果我们用Math
replacenull
,事情将按预期工作,string“foo”将被打印到屏幕上(我使用Mozilla Rhinotesting了这个)。
你几乎可以假设没有人装饰Math.max
所以传递null
将毫无问题地工作。
还有一种方法可以做到这一点:
var arrayMax = Function.prototype.apply.bind(Math.max, null);
用法:
var max = arrayMax([2, 5, 1]);
我很惊讶没有人提到减lessfunction。
var arr = [1, 10, 5, 11, 2] var b = arr.reduce(function(previous,current){ return previous > current ? previous:current }); b => 11 arr => [1, 10, 5, 11, 2]
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math/max
function getMaxOfArray(numArray) { return Math.max.apply(null, numArray); } var arr = [100, 0, 50]; console.log(getMaxOfArray(arr))
对于大数组(〜10个元素), Math.min
和Math.max
会在node.js中引发RangeError(超出最大调用堆栈大小)。
对于大数组,一个快速和肮脏的解决scheme是:
Array.prototype.min = function() { var r = this[0]; this.forEach(function(v,i,a){if (v<r) r=v;}); return r; };
我有同样的问题,我需要获得一个数组的最小值和最大值,令我惊讶的是,没有数组的内置函数。 阅读了很多之后,我决定自己testing“前三名”解决scheme:
- 离散解决scheme:一个FOR循环来检查数组的每个元素与当前的最大值和/或最小值;
- APPLY解决scheme:使用apply(null,array)将数组发送到Math.max和/或Math.min内部函数。
- REDUCE解决scheme:使用reduce(function)对数组中的每个元素进行recursion检查。
testing代码是这样的:
function GetMaxDISCRETE(A) { var MaxX=A[0]; for (var X=0;X<A.length;X++) if (MaxX<A[X]) MaxX=A[X]; return MaxX; } function GetMaxAPPLY(A) { return Math.max.apply(null,A); } function GetMaxREDUCE(A) { return A.reduce(function(p,c) { return p>c?p:c; }); }
数组A填充了100,000个随机整数,每个函数在带有Windows Vista的Intel Pentium 4 2.99GHz桌面的Mozilla Firefox 28.0上执行10,000次。 时间以秒为单位,通过performance.now()函数检索。 结果是这些,有3个小数位和标准偏差:
- 离散解:平均值= 0.161s,sd = 0.078
- 申请解决scheme:平均= 3.571s,sd = 0.487
- 减less解决scheme:平均= 0.350s,sd = 0.044
REDUCE解决scheme比分立式解决scheme慢117%。 APPLY解决scheme更糟,比分立解决scheme慢了2,118%。 此外,正如彼得所观察到的,它不适用于大型数组(大约有一百多万个元素)。
另外,为了完成testing,我testing了这个扩展的离散代码:
var MaxX=A[0],MinX=A[0]; for (var X=0;X<A.length;X++) { if (MaxX<A[X]) MaxX=A[X]; if (MinX>A[X]) MinX=A[X]; }
时间:平均= 0.218s,sd = 0.094
因此,它比简单的离散解决scheme慢35%,但它一次检索最大值和最小值(任何其他解决scheme至less需要检索它们的两倍)。 一旦OP需要两个值,离散解决scheme将是最好的select(即使作为两个独立的function,一个用于计算最大值,另一个用于计算最小值,他们将胜过次优,REDUCE解决scheme)。
您可以在项目的任何位置使用以下function:
function getMin(array){ return Math.min.apply(Math,array); } function getMax(array){ return Math.max.apply(Math,array); }
然后你可以调用传递数组的函数:
var myArray = [1,2,3,4,5,6,7]; var maximo = getMax(myArray); //return the highest number
这可能适合你的目的。
Array.prototype.min = function(comparer) { if (this.length === 0) return null; if (this.length === 1) return this[0]; comparer = (comparer || Math.min); var v = this[0]; for (var i = 1; i < this.length; i++) { v = comparer(this[i], v); } return v; } Array.prototype.max = function(comparer) { if (this.length === 0) return null; if (this.length === 1) return this[0]; comparer = (comparer || Math.max); var v = this[0]; for (var i = 1; i < this.length; i++) { v = comparer(this[i], v); } return v; }
迭代,保持跟踪。
var min = null; var max = null; for (var i = 0, len = arr.length; i < len; ++i) { var elem = arr[i]; if (min === null || min > elem) min = elem; if (max === null || max < elem) max = elem; } alert( "min = " + min + ", max = " + max );
如果数组中没有元素,这将使min / max为null。 如果数组有任何元素,将在一次传递中设置最小值和最大值。
你也可以使用上面的range
方法来扩展Array,以允许重用和提高可读性。 在http://jsfiddle.net/9C9fU/看到一个工作小提琴;
Array.prototype.range = function() { var min = null, max = null, i, len; for (i = 0, len = this.length; i < len; ++i) { var elem = this[i]; if (min === null || min > elem) min = elem; if (max === null || max < elem) max = elem; } return { min: min, max: max } };
用作
var arr = [3, 9, 22, -7, 44, 18, 7, 9, 15]; var range = arr.range(); console.log(range.min); console.log(range.max);
简单的东西,真的。
var arr = [10,20,30,40]; arr.max = function() { return Math.max.apply(Math, this); }; //attach max funct arr.min = function() { return Math.min.apply(Math, this); }; //attach min funct alert("min: " + arr.min() + " max: " + arr.max());
这是从一个对象数组中获取最大值的一种方法。 创build一个副本(带切片),然后按降序对副本进行sorting并抓取第一个项目。
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;
使用Math.max()
或Math.min()
Math.max(10, 20); // 20 Math.min(-10, -20); // -20
以下函数使用Function.prototype.apply()
来查找数字数组中的最大元素。 getMaxOfArray([1, 2, 3])
等价于Math.max(1, 2, 3)
,但是可以使用getMaxOfArray()
构造任意大小的数组。
function getMaxOfArray(numArray) { return Math.max.apply(null, numArray); }
或者用新的扩展运算符,获得数组的最大值变得更容易。
var arr = [1, 2, 3]; var max = Math.max(...arr); // 3 var min = Math.min(...arr); // 1
我想我会分享我简单易懂的解决scheme。
对于分:
var arr = [3, 4, 12, 1, 0, 5]; var min = arr[0]; for (var k = 1; k < arr.length; k++) { if (arr[k] < min) { min = arr[k]; } } console.log("Min is: " + min);
如果您使用原型,ChaosPandion的解决scheme就可以工作。 如果没有,请考虑这一点:
Array.max = function( array ){ return Math.max.apply( Math, array ); }; Array.min = function( array ){ return Math.min.apply( Math, array ); };
如果一个数组值不是一个整数,上面将返回NaN,所以你应该build立一些function来避免这种情况。 否则这将工作。
如果你正在使用prototype.js框架,那么这个代码将正常工作:
arr.min(); arr.max();
logging在这里: Javascript原型框架最大
如果你使用库糖sugar.js ,你可以写你的build议arr.min()和arr.max() 。 您还可以从非数字数组中获取最小值和最大值。
min(map,all = false)返回数组中元素的最小值。 map可以是映射要检查的值或作为快捷方式的string的函数。 如果全部为真,将返回数组中的所有最小值。
max(map,all = false)返回数组中具有最大值的元素。 map可以是映射要检查的值或作为快捷方式的string的函数。 如果全部为真,将返回数组中的所有最大值。
例子:
[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这样的库也提供了类似的强大的最小和最大函数:
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 }
minHeight = Math.min.apply({},YourArray); minKey = getCertainKey(YourArray,minHeight); maxHeight = Math.max.apply({},YourArray); maxKey = getCertainKey(YourArray,minHeight); function getCertainKey(array,certainValue){ for(var key in array){ if (array[key]==certainValue) return key; } }
我喜欢Linus的reduce()方法 ,特别是对于大型数组。 但只要你知道你需要min和max,为什么迭代数组两次?
Array.prototype.minmax = function () { return this.reduce(function (p, v) { return [(p[0] < v ? p[0] : v), (p[1] > v ? p[1] : v)]; }, [this[0], this[0]]); }
当然,如果你喜欢迭代的方法,你也可以这样做:
Array.prototype.minmax = function () { var mn = this[0], mx = this[0]; this.forEach(function (v) { if (v < mn) mn = v; if (v > mx) mx = v; }); return [mn, mx]; };
创build一个简单的对象
var myArray = new Array(); myArray = [10,12,14,100]; var getMaxHeight = { hight : function( array ){ return Math.max.apply( Math, array ); } getMaxHeight.hight(myArray);
下面的脚本在ndoejs为我工作:
var numbers = [1, 2, 3, 4]; console.log('Value:: ' + Math.max.apply(null, numbers) ); // 4
find元素Array
的最小值的简单方法是使用Array
原型函数reduce
:
A = [4,3,-9,-2,2,1]; A.reduce((min, val) => val < min ? val : min, A[0]); // returns -9
这将min
设置为A[0]
,然后检查A[1]...A[n]
是否严格小于当前min
。
以下代码适用于我:
var valueList = [10,4,17,9,3]; var maxValue = valueList.reduce(function(a, b) { return Math.max(a, b); }); var minValue = valueList.reduce(function(a, b) { return Math.min(a, b); });