Skip to content

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

Description

@mqyqingfeng

前言

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

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,对作者也是一种鼓励。

Activity

  1. shixuev5 commented on Jul 25, 2017

    @shixuev5

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

  2. mqyqingfeng commented on Jul 25, 2017

    @mqyqingfeng
    OwnerAuthor

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

    default

  3. jiangshanmeta commented on Nov 3, 2017

    @jiangshanmeta

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

  4. mqyqingfeng commented on Nov 8, 2017

    @mqyqingfeng
    OwnerAuthor

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

  5. MillionQW commented on Dec 5, 2017

    @MillionQW

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

  6. roadwild commented on Dec 5, 2017

    @roadwild

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

  7. mqyqingfeng commented on Dec 6, 2017

    @mqyqingfeng
    OwnerAuthor

    @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)");
  8. mqyqingfeng commented on Dec 6, 2017

    @mqyqingfeng
    OwnerAuthor

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

  9. MillionQW commented on Dec 7, 2017

    @MillionQW

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

  10. crowphy commented on Jan 8, 2018

    @crowphy

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

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

  11. mqyqingfeng commented on Jan 10, 2018

    @mqyqingfeng
    OwnerAuthor

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

  12. mqyqingfeng commented on Mar 8, 2018

    @mqyqingfeng
    OwnerAuthor

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

  13. Tan90Qian commented on Apr 17, 2018

    @Tan90Qian

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

  14. mqyqingfeng commented on Apr 24, 2018

    @mqyqingfeng
    OwnerAuthor

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

  15. aierong commented on Oct 15, 2018

    @aierong

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

    var arr = [ ];

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

  16. MoYummy commented on Nov 4, 2018

    @MoYummy

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

  17. hubvue commented on Dec 2, 2018

    @hubvue

    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

  18. inottn commented on Dec 11, 2018

    @inottn

    @MoYummy

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

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

  19. world8023 commented on Jan 3, 2019

    @world8023

    @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,{},]))

  20. gongph commented on Apr 15, 2020

    @gongph

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

    Reflect.apply(Math.max, Math, [1,2,3])
    // -> 3
  21. angelayun commented on May 17, 2020

    @angelayun

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

    var arr = [ ];

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

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

  22. TyrionJYQ commented on Sep 25, 2020

    @TyrionJYQ

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

  23. Quantum-Boy commented on May 7, 2021

    @Quantum-Boy

    @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

  24. dzsqe commented on Jun 17, 2021

    @dzsqe

    @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"),参数是字符串肯定不行

  25. caowanjing-code commented on Sep 23, 2021

    @caowanjing-code

    thank you for your provided!

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions