Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript专题之如何求数组的最大值和最小值 #35

Open
mqyqingfeng opened this issue Jul 19, 2017 · 28 comments
Open

JavaScript专题之如何求数组的最大值和最小值 #35

mqyqingfeng opened this issue Jul 19, 2017 · 28 comments

Comments

@mqyqingfeng
Copy link
Owner

前言

取出数组中的最大值或者最小值是开发中常见的需求,但你能想出几种方法来实现这个需求呢?

Math.max

JavaScript 提供了 Math.max 函数返回一组数中的最大值,用法是:

Math.max([value1[,value2, ...]])

值得注意的是:

  1. 如果有任一参数不能被转换为数值,则结果为 NaN。
  2. max 是 Math 的静态方法,所以应该像这样使用:Math.max(),而不是作为 Math 实例的方法 (简单的来说,就是不使用 new )
  3. 如果没有参数,则结果为 -Infinity (注意是负无穷大)

而我们需要分析的是:

1.如果任一参数不能被转换为数值,这就意味着如果参数可以被转换成数字,就是可以进行比较的,比如:

Math.max(true, 0) // 1
Math.max(true, '2', null) // 2
Math.max(1, undefined) // NaN
Math.max(1, {}) // NaN

2.如果没有参数,则结果为 -Infinity,对应的,Math.min 函数,如果没有参数,则结果为 Infinity,所以:

var min = Math.min();
var max = Math.max();
console.log(min > max);

了解了 Math.max 方法,我们以求数组最大值的为例,思考有哪些方法可以实现这个需求。

原始方法

最最原始的方法,莫过于循环遍历一遍:

var arr = [6, 4, 1, 8, 2, 11, 23];

var result = arr[0];
for (var i = 1; i < arr.length; i++) {
    result =  Math.max(result, arr[i]);
}
console.log(result);

reduce

既然是通过遍历数组求出一个最终值,那么我们就可以使用 reduce 方法:

var arr = [6, 4, 1, 8, 2, 11, 23];

function max(prev, next) {
    return Math.max(prev, next);
}
console.log(arr.reduce(max));

排序

如果我们先对数组进行一次排序,那么最大值就是最后一个值:

var arr = [6, 4, 1, 8, 2, 11, 23];

arr.sort(function(a,b){return a - b;});
console.log(arr[arr.length - 1])

eval

Math.max 支持传多个参数来进行比较,那么我们如何将一个数组转换成参数传进 Math.max 函数呢?eval 便是一种

var arr = [6, 4, 1, 8, 2, 11, 23];

var max = eval("Math.max(" + arr + ")");
console.log(max)

apply

使用 apply 是另一种。

var arr = [6, 4, 1, 8, 2, 11, 23];
console.log(Math.max.apply(null, arr))

ES6 ...

使用 ES6 的扩展运算符:

var arr = [6, 4, 1, 8, 2, 11, 23];
console.log(Math.max(...arr))

有更多的方法欢迎留言哈~

专题系列

JavaScript专题系列目录地址:https://github.com/mqyqingfeng/Blog

JavaScript专题系列预计写二十篇左右,主要研究日常开发中一些功能点的实现,比如防抖、节流、去重、类型判断、拷贝、最值、扁平、柯里、递归、乱序、排序等,特点是研(chao)究(xi) underscore 和 jQuery 的实现方式。

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。

@shixuev5
Copy link

@zhqgit var arr = [6, 4, 1, 8, 2, 11, 23];
console.log(...arr ) // 6 4 1 8 2 11 23

@mqyqingfeng
Copy link
Owner Author

@shixuev5 感谢回答哈~
@zhqgit 扩展运算符(...)可以将一个数组变为参数序列,引用阮一峰老师的《ECMAScript 6 入门》

default

@jiangshanmeta
Copy link

还以为要从头实现一个underscore的_.max _.min呢

@mqyqingfeng
Copy link
Owner Author

@jiangshanmeta 嗯好,四个系列完结后,我会重新修订这些内容,到时候一定补充上这些内容~

@MillionQW
Copy link

你好,可以请教一下eval求数组最大值的原理是什么吗?已知给eval()传入字符串,如果字符串是表达式的话就会被执行,但是不明白为什么把Math.max( 和右括号转出字符串中间夹个数组就能求出最大值。

@roadwild
Copy link

roadwild commented Dec 5, 2017

@MillionQW 因为数组被转换成字符串了啊。。。

@mqyqingfeng
Copy link
Owner Author

@MillionQW 这是因为发生了隐式类型转换,举个简单例子:

var arr = [6, 4, 1, 8, 2, 11, 23];
console.log(arr + ''); // 6,4,1,8,2,11,23

其实

var max = eval("Math.max(" + arr + ")");

其实就相当于

var max = eval("Math.max(6,4,1,8,2,11,23)");

@mqyqingfeng
Copy link
Owner Author

@sinkinlife 感谢回答哈~ ( ̄▽ ̄)~*

@MillionQW
Copy link

哈哈哈懂了,谢谢两位的回答~

@crowphy
Copy link

crowphy commented Jan 8, 2018

JavaScript 提供了 Math.max 函数返回一组数中的最大值,用法是:
Math.max([value1[,value2, ...]])

这样写容易让人以为传入的是个数组,比如我。。。

@mqyqingfeng
Copy link
Owner Author

@crowphy 哈哈,这个用的是 MDN 的写法,这个方括号是用来表示该参数非必填,可以传也可以不传……如果不用 [] 的话,我不知道对于非必填参数怎么描述了……

@ghost
Copy link

ghost commented Mar 5, 2018

function Max(array) {
    return array.reduce((a,b)=>a > b ? a : b)
}

@mqyqingfeng
Copy link
Owner Author

@Panzhipeng1 好方法,感谢补充哈~

@Tan90Qian
Copy link

@Panzhipeng1 如果传入一组正确的参数给Math.max方法,返回的结果都是"number"类型的,而你这个并没有进行类型转化,两者的结果并不一致。当然这得看实际的需求需不需要进行类型转化,以及“最大”和“最小”是依据什么来判断的。

@mqyqingfeng
Copy link
Owner Author

@Tan90Qian 好思路,都没有注意到这一点~ (๑•̀ㅂ•́)و✧

@aierong
Copy link

aierong commented Oct 15, 2018

用reduce,求最大最小有点小风险,当arr为空数组时,代码运行会报错
所以,运行前最好做个判断

var arr = [ ];

function max(prev, next) {
return Math.max(prev, next);
}
console.log(arr.reduce(max));

@MoYummy
Copy link

MoYummy commented Nov 4, 2018

Math.max.apply(null, arr),用对象null调用参数为arr的max方法,这原理为什么能成功?

@hubvue
Copy link

hubvue commented Dec 2, 2018

ES6中也可以用Reflect的方式实现求数组的最大值和最小值
例:var arr = = [1,2,7,9,3,4,5];
Relfect.apply(Math.max,Math,arr) // 9
Reflect.apply(Math.min,Math,arr) //1

@inottn
Copy link

inottn commented Dec 11, 2018

@MoYummy

apply() 方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。
简单来说第一个参数就是改变原函数运行时的 this 值。
一些原型上的方法作用的对象是其 this 值。
比如使用 Array.prototype.slice.apply(arguments)arguments 对象转换为数组。

max()Math 的静态方法,调用时方法内 this 值对结果没有影响。

@world8023
Copy link

@mqyqingfeng 楼主好,这也算一种最简单的方法吧,并且有{}或者undefined也能正常运行,function sortArr(arr) {
var max = min = arr[0];
for (var i = 0; i < arr.length; i++) {
arr[i] > max ? max = arr[i] : '';
arr[i] < min ? min = arr[i] : '';
}
return [max, min]
}
console.log(sortArr([11, 3, 5, 3, 66, 22, 66, 33, 565, 2222, 4, 3,{},]))

@gongph
Copy link

gongph commented Apr 15, 2020

😊大佬学习了!另外 Reflect 也有一种方式,即:

Reflect.apply(Math.max, Math, [1,2,3])
// -> 3

@angelayun
Copy link

用reduce,求最大最小有点小风险,当arr为空数组时,代码运行会报错
所以,运行前最好做个判断

var arr = [ ];

function max(prev, next) {
return Math.max(prev, next);
}
console.log(arr.reduce(max));

你写成这样就不报错了
console.log(arr.reduce(max,[]));

@TyrionJYQ
Copy link

Math.max.apply(null, arr),用对象null调用参数为arr的max方法,这原理为什么能成功?
和null没什么关系,主要是apply的第二个参数是数组,在没有...运算符前基本都是用apply对数组进行展开的

@Quantum-Boy
Copy link

@MillionQW 这是因为发生了隐式类型转换,举个简单例子:

var arr = [6, 4, 1, 8, 2, 11, 23];
console.log(arr + ''); // 6,4,1,8,2,11,23

其实

var max = eval("Math.max(" + arr + ")");

其实就相当于

var max = eval("Math.max(6,4,1,8,2,11,23)");

var max = Math.max((arr + '')),使用这个为啥就不行了呢,打印出来的是NaN

@dzsqe
Copy link

dzsqe commented Jun 17, 2021

@MillionQW 这是因为发生了隐式类型转换,举个简单例子:

var arr = [6, 4, 1, 8, 2, 11, 23];
console.log(arr + ''); // 6,4,1,8,2,11,23

其实

var max = eval("Math.max(" + arr + ")");

其实就相当于

var max = eval("Math.max(6,4,1,8,2,11,23)");

var max = Math.max((arr + '')),使用这个为啥就不行了呢,打印出来的是NaN

Math.max((arr + '')) 等于Math.max("6,4,1,8,2,11,23"),参数是字符串肯定不行

@caowanjing-code
Copy link

thank you for your provided!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests