本文汇总了 JavaScript 中提取二维数组最大值的方法。从基础的双重 for 循环,到使用 Array.prototype.map 结合 reduce 的高级写法,再到利用 Function.prototype.apply.bind 实现极简代码。此外,还探讨了通过 join 和 split 处理多维数组最大值的技巧,并提供了完整代码示例与性能对比分析。
JavaScript 获取二维及多维数组最大值的三种实现方案
在 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 循环,用于遍历当前子数组中的每一个元素。
使用 if 语句判断当前子数组元素是否大于当前存储的 largestNumber。若条件成立(true),则将该元素值赋给 largestNumber。
内部循环结束后,将每个子数组计算出的最大值存入最初声明的 results 数组中。
最后,返回包含所有子数组最大值的 results 数组。
在获取所有子数组的最大值并生成新数组 results 后,只需通过以下代码:
扩展 Array.prototype.max
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
中级解决方案
中级解决方案
Map 结合 Reduce 方法
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.apply.bind 极简写法
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() 方法实现:
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) 来取数组中最大的数字。这篇文章从不同角度介绍了如何在二维数组中取出最大的数,但很多时候,数组还有多维数组,文章最后介绍了如何实现多维数组中取出最大值。如果您有更多的方案,欢迎在评论中与我们一起分享。