JS中取二维数组中最大值的方法汇总


Posted in Javascript onApril 17, 2016

在JavaScript中可以通过内置的 Math.max() 的最大值,但是要从多重数组中取出最大值,还是有一定的难度。

问题描述

假设你有一个数组,而且这个数组中包含了数字的子数组,而我们要做的是从数组中的每个子数组中返回其最大的那个最大数。

基本解决方案

function largestOfFour(arr) {
var results = []; // 创建一个results变量来存储
// 创建一个外层循环,遍历外层数组
for (var n = 0; n < arr.length; n++) {
var largestNumber = 0; // 创建第二个变量,存储最大的数
// 创建另一个循环,遍历子数组
for (var sb = 0; sb < arr[n].length; sb++) {
//检查子数组的元素是否大于当前存储的最大值
if (arr[n][sb] > largestNumber) {
// 如果为真,将这个值赋予给变量largestNumber
largestNumber = arr[n][sb];
}
}
// 内部循环后,将每个子数组中的值保存到数组results中
results[n] = largestNumber;
}
// 返回数组
return results;
}
largestOfFour([[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]]); //[34, 456, 4567, 78]

上面的方法是一个普通的解决方案,通过两个 for 循环对数组及其子数组做遍历:

创建一个 results 变量用来存储每个子数组中遍历出来的最大值

创建外循环 for 遍历外层数组

创建第二个变量 largestNumber 用来存放最大值。这个变量值必须放在内部 for 循环的外面,因为这样他才不会被重新分配

创建第二个 for 循环,来遍历子数组中的每个元素

通过一个 if 语句来判断当前子数组的元素是否大于当前存储的最大值 largestNumber 。如果是( true ),将这个最大值存储给 largestNumber 。

内部循环结束后,将每个子数组中的最大值存储到最初声明的变量 results 中

最后返回 results 数组

取出所有子数组中的每个最大值之后,得到一个新数组 results ,这个时候只需要通:

Array.prototype.max = function () {
return Math.max.apply({},this);
}
largestOfFour(arr).max();

就可以得到其中的最大值。

largestOfFour([[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]]).max(); // 4567

中级解决方案

function largestOfFour (arr) {
// 通过map()方法,并通过回调函数,将子数组中最大值组合在一起,得到一新数组
return arr.map(function (group) {
// 通过reduce方法,把每个子数组中最大值返回到group数组中
return group.reduce(function (prev, current) {
// 如果current 大于prev,返回current,否则返回prev
return (current > prev) ? current : prev;
});
});
}
largestOfFour([[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]]); // [34, 456, 4567, 78]

在外层数组中使用 Array.prototype.map() 方法遍历数组。使用 map() 方法遍历数组,会调用一个回调函数,在这个回调函数中,使用 reduce() 方法对每个子数组 group 进行合并,将值返回到一个新数组中。而在使用 reduce() 方法时,同样会调用一个回调函数,这个回调函数只做了一件事情,就是子数组中的元素做为比较,如果 current 大于 prev ,将会返回 current ,否则返回 prev ,最终得到每个子数组中最大值。

和前面一样,通过 Math.max.apply() 最终得到最大值。

最佳解决方案

function largestOfFour (arr) {
return arr.map(Function.apply.bind(Math.max, null));
}
largestOfFour([[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]]); //[34, 456, 4567, 78]

这个方案,使用 Function.bind 方法创建一个特殊的回调函数,就类似于 Math.max 方法一样,但其有一个 Function.prototype.apply 功能,将数组作为它的参数。

先对主数组中的每个元素做遍历,也就是数组内部的每个子数组

使用 map() 方法需要一个回调函数,用来找出内部每个数组中的最大值。需要创建一个函数,让 Math.max 能接受输入的数组工作。换句话说,这是非常简单而且这样工作也非常的好,如 Math.max([9,43,20,6]); 将会返回最大值 43

Function.prototype.apply 方法工作可以接受数组做为参数,但函数通过调用上下文,这事情就有点复杂。例如 Math.max.apply(null,[9,43,20,6]) 将调用一个 Max.max 方法,但这样的方法找起来不容易。

这里给 Function.prototype.apply 方法传递了一个 null 参数,告诉 Math.max 不需要任何上下文。

因为 arr.map() 需要一个回调函数,而不只是一个表达式,我们在 Function.bind 方法中提供了一个函数

因为 Function.prototype.apply 是一个静态方法,类似一个函数对象,我们可以称之为 Function.prototype.apply 上绑定了一个 Function.prototype.bind 。例如: Function.apply.bind

现在可以通过 Function.prototype.apply.bind 回调函数指定其上下文,比如在这个示例中的 Math.max 方法

由于是嵌入到 Function.prototype.apply 方法,需要一个上下文作为第一个参数,而且这个上下文还是一个虚假的。

所以我们将 null 作为第二个参数传递给 Function.prototype.apply.bind ,并且绑定一个上下文,这个上下文就是 Math.max 方法

由于 Math.max 是独立于任何上下文的,所以它会忽略 Function.prototype.apply 方法调用的虚假上下文

我们使用 Function.prototype.apply.bind(Math.max,null) 让一个新函数接受 arr.map 值,比如数组中的子数组

多维数组中取最大值

上文使用不同的方法实现了从二维数组中取出子数组中最大值,并且将这些最大值重新组成一个新数组,如果延伸一下,取出里面的最大值时,还需要使用 Array.prototype.max 函数,函数中通过 Math.max.apply({},this) 取得最大值。不过如果不是二维数组,那上述方法将无法取出数组中最大的值。

而在多维数组中取最大值,可以通过 join() 和 split() 方法组合在一起:

function largestOfFour (arr) {
var newArray = arr.join(",").split(",");
return Math.max.apply({},newArray);
}
largestOfFour([12,23]); // =>23
largestOfFour([12,23,[1234,324],[345,566]]); // =>1234
largestOfFour([12,23,[1234,324,[23121,90890]],[345,566,[345,78,90]]]); // =>90890
largestOfFour([12,23,[1234,324,[23121,90890]],[345,566,[345,78,90,[90909090,988]]]]); // =>90909090

同样可以使用类似的方法取出多维数组中的最小值:

function smallerOfFour (arr) {
var newArray = arr.join(",").split(",");
return Math.min.apply({},newArray);
}
smallerOfFour([12,23]); // =>12
smallerOfFour([112,23,[1234,324],[345,566]]); // =>23
smallerOfFour([212,123,[1234,324,[23121,90890]],[345,566,[345,78,90]]]); // =>78
smallerOfFour([102,230,[1234,324,[23121,90890]],[345,566,[345,78,90,[90909090,988]]]]); // =>78

总结

在《 JavaScript学习笔记:取数组中最大值和最小值 》一文中介绍了使用 Math.max.apply({},arr) 来取数组中最大的数字。这篇文章中从不同的角度的介绍了如何在二维数组中取出最大的数,但很多时候,数组还有多维数组,文章最后介绍了如何实现多维数组中取出最大值。如果您有更多的方案,欢迎在评论中与我们一起分享。

Javascript 相关文章推荐
javascript中使用replaceAll()函数实现字符替换的方法
Dec 25 Javascript
js获取GridView中行数据的两种方法 分享
Jul 13 Javascript
jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮
Oct 11 Javascript
ajax如何实现页面局部跳转与结果返回
Aug 24 Javascript
每天一篇javascript学习小结(基础知识)
Nov 10 Javascript
javascript获取select标签选中的值
Jun 04 Javascript
Bootstrap模态框(Modal)实现过渡效果
Mar 17 Javascript
探索webpack模块及webpack3新特性
Sep 18 Javascript
layui框架table 数据表格的方法级渲染详解
Aug 19 Javascript
vue 使用鼠标滚动加载数据的例子
Oct 31 Javascript
js实现坦克大战游戏
Feb 24 Javascript
js+for循环实现字符串自动转义的代码(把后面的字符替换前面的字符)
Dec 24 Javascript
JS组件Bootstrap ContextMenu右键菜单使用方法
Apr 17 #Javascript
js实现select二级联动下拉菜单
Apr 17 #Javascript
基于javascript实现精确到毫秒的倒计时限时抢购
Apr 17 #Javascript
第二次聊一聊JS require.js模块化工具的基础知识
Apr 17 #Javascript
第一次接触JS require.js模块化工具
Apr 17 #Javascript
jqGrid 学习笔记整理——进阶篇(一 )
Apr 17 #Javascript
JS组件Bootstrap dropdown组件扩展hover事件
Apr 17 #Javascript
You might like
PHP数组内存耗用太多问题的解决方法
2010/04/05 PHP
php cache类代码(php数据缓存类)
2010/04/15 PHP
PHP 一个随机字符串生成代码
2010/05/26 PHP
深入PHP购物车模块功能分析(函数讲解,附源码)
2013/06/25 PHP
php的一个简单加密解密代码
2014/01/14 PHP
PHP中把stdClass Object转array的几个方法
2014/05/08 PHP
php冒泡排序与快速排序实例详解
2015/12/07 PHP
PHP实现的多维数组去重操作示例
2018/07/21 PHP
laravel 字段格式化 modle 字段类型转换方法
2019/09/30 PHP
javascript实现状态栏文字首尾相接循环滚动的方法
2015/07/22 Javascript
超详细的javascript数组方法汇总
2015/11/21 Javascript
Ionic快速安装教程
2016/06/03 Javascript
Angular5中调用第三方js插件的方法
2018/02/26 Javascript
JS同步、异步、延迟加载的方法
2018/05/05 Javascript
详解Ant Design of React的安装和使用方法
2018/12/27 Javascript
解决element ui select下拉框不回显数据问题的解决
2019/02/20 Javascript
axios如何利用promise无痛刷新token的实现方法
2019/08/27 Javascript
JSON stringify方法原理及实例解析
2020/10/23 Javascript
[55:44]完美世界DOTA2联赛决赛 FTD vs Phoenix 第二场 11.08
2020/11/11 DOTA
一个简单的python程序实例(通讯录)
2013/11/29 Python
Python生命游戏实现原理及过程解析(附源代码)
2019/08/01 Python
Python修改列表值问题解决方案
2020/03/06 Python
python 通过pip freeze、dowload打离线包及自动安装的过程详解(适用于保密的离线环境
2020/12/14 Python
Weblogic的布署方式
2013/08/23 面试题
中药专业大学生医药工作求职信
2013/10/25 职场文书
生产车间班组长岗位职责
2014/01/06 职场文书
酒店保安领班职务说明书
2014/03/04 职场文书
大学生英语演讲稿
2014/04/24 职场文书
中文专业毕业生自荐信
2014/05/24 职场文书
设备售后服务承诺书
2014/05/30 职场文书
个人汇报材料范文
2014/12/30 职场文书
创业者如何撰写出一份打动投资人的商业计划书?
2019/07/02 职场文书
承诺书的签字人,需不需要承担相应的责任?
2019/07/09 职场文书
浅谈JS的原型和原型链
2021/06/04 Javascript
聊聊基于pytorch实现Resnet对本地数据集的训练问题
2022/03/25 Python
SQL Server中T-SQL标识符介绍与无排序生成序号的方法
2022/05/25 SQL Server