数组的元素可能是数组,这样一层层嵌套,可能得到一个嵌套很深的数组,数组降维要做的事就是把嵌套很深的数组展开,一般最后得到一个一维数组,其中的元素都是非数组元素,比如数组[1, [2, 3, [4, 5], 6], 7, 8]降维展开后是[1, 2, 3, 4, 5, 6, 7, 8].

1.普通方法

  1. function flattenMd(arr){
  2. var result=[]
  3. function flatten(arr){
  4. for (var i = 0; i < arr.length; i++) {
  5. if (Array.isArray(arr[i])) {
  6. flatten(arr[i]);
  7. }else{
  8. result.push(arr[i]);
  9. }
  10. }
  11. }
  12. flatten(arr);
  13. return result;
  14. }
  15. var arr=[1, [2, 3, [4, 5], 6], 7, 8]
  16. console.log(flattenMd(arr));[ 1, 2, 3, 4, 5, 6, 7, 8 ]

备注:这里我使用了Array.isArray()方法来检测对象时候是数组,没有考虑ES5以下的兼容性,关于js对象类型的检测可以参考我的另一篇博文Javascript数据类型检测,当然了如果支持ES5的话,还可以直接使用数组的迭代方法forEach(或map、reduce等),Es6中还有for···in可以使用,这里就不赘述了。

这个方法需要定义两个函数,其中flatten方法位于内部。还可以改造成闭包的形式

  1. function flattenMd(ret) {
  2. function flatten(arr) {
  3. arr.forEach(function(item) {
  4. (Array.isArray(item)) ? flatten(item) : ret.push(item);
  5. });
  6. }
  7. return function(arr) {
  8. flatten(arr);
  9. return ret;
  10. }
  11. }([]);
  12. var arr=[1, [2, 3, [4, 5], 6], 7, 8]
  13. console.log(flattenMd(arr));[ 1, 2, 3, 4, 5, 6, 7, 8 ]

2.数组concat方法

熟悉数组操作方法的开发人员应该知道数组concat方法的特性:传递给concat方法的参数序列中如果包含数组,则会将这个数组的每一项添加到结果数组中,这就使数组的这个方法具有了天然的展开二维数组的能力,比如:

  1. var colors=['red','green','blue'];
  2. var colors2=colors.concat('yellow',['black','brown']);
  3. console.log(colors2)//[ 'red', 'green', 'blue', 'yellow', 'black', 'brown' ]

需要注意的是如果数组的元素还是数组则不会再展开了,也就是concat方法只能降低一维。借助concat方法,可以得到另一种二维数组降维方法。

  1. function flatten2d(arr) {
  2. var result = [];
  3. for(var i = 0; i < arr.length; i++) {
  4. result = result.concat(arr[i]);
  5. }
  6. return result;
  7. }

上面的方法还可以进一步简化。我们知道apply方法是可以直接接受数组参数,这样我们连循环迭代都省了。

  1. function flatten2d(arr) {
  2. return Array.prototype.concat.apply([], arr);
  3. }

网上很多博客说使用递归很容易将二维的降维改造成多维的降维,实际上操作起来是比较复杂的,因为没有现成的方法能够判断某个数组是不是二维数组,也就不能判断递归的结束条件了。所以对于多维数组的降维需要重新规划使用concat方法可以避免方法一中多出的内部函数

对于多维数组

  1. function flattenMd(arr) {
  2. var result = [];
  3. for(var i = 0; i < arr.length; i++){
  4. if(arr[i] instanceof Array) {
  5. result = result.concat(flattenMd(arr[i]));
  6. }
  7. else {
  8. result.push(arr[i]);
  9. }
  10. }
  11. return result;
  12. }
  13. var arr=[1, [2, 3, [4, 5], 6], 7, 8]
  14. console.log(flattenMd(arr));[ 1, 2, 3, 4, 5, 6, 7, 8 ]

3.数组join和split方法的结合(有缺陷)

很多开发人员都知道数组的join方法可以将数组展开成字符串,但是不确定的是join方法能够展平数组,即使是多维数组,我们再使用split方法重新组合数组就行了。但是这个方法有天然缺陷,下面的例子中会看到

  1. function flattenMd(arr) {
  2. return arr.join().split(',');
  3. }
  4. var arr=['1', [null, 3, [4, 5], {K:1}], undefined, 8]
  5. console.log(flattenMd(arr));//[ '1', '', '3', '4', '5', '[object Object]', '', '8' ]

从结果可以看出,这样处理过后有几个缺点:一是所有类型的元素都会变成字符串;二是null、undefined会变成空字符串、对象会变成'[object Object]'。相当于调用了toString方法,当也不是说这个方法一无是处。对于同一种类型的元素,还是很有用处的,比如要求多维数组的最大值。

  1. function flattenMd(arr) {
  2. return arr.join().split(',');
  3. }
  4. var arr=[1, [5, 3, [8, 5], 5,[15]], 9, 13]
  5. console.log(Math.max.apply(null,flattenMd(arr)));//15

参考

优雅的数组降维——Javascript中apply方法的妙用

Javascript实现的数组降维——维度不同,怎么谈恋爱的更多相关文章

  1. Javascript实现的数组降维——维度不同,怎么谈恋爱(修订版)

    数组的元素可能是数组,这样一层层嵌套,可能得到一个嵌套很深的数组,数组降维要做的事就是把嵌套很深的数组展开,一般最后得到一个一维数组,其中的元素都是非数组元素,比如数组[1, [2, 3, [4, 5 ...

  2. 优雅的数组降维——Javascript中apply方法的妙用

    将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转换.本文将从朴素的循环转换开始,逐一介绍三 ...

  3. 数组降维-JavaScript中apply方法妙用

    海纳百川,有容乃大 1.普通循环转换方式 将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转 ...

  4. JavaScript学习笔记——数组

    javascript数组数组是一个可以存储 一组 或是 一系列 相关数据 的 容器. 一.为什么要使用数组. (1)为了解决大量相关数据的存储和使用的问题. (2)模拟真是的世界. 二.如何创建数组 ...

  5. php中使用array_reduce给数组降维

    PHP里面最强大的工具,就是数组,它融合了多种数据结构的特点,数组.队列.栈.哈希表等等,而且容器可以兼容各种类型,任意嵌套,简直无所不能.围绕着数组,PHP原生支持了一些列的函数,使得数组在实际编程 ...

  6. 面试官:JavaScript如何实现数组拍平(扁平化)方法?

    面试官:JavaScript如何实现数组拍平(扁平化)方法? 1 什么叫数组拍平? 概念很简单,意思是将一个"多维"数组降维,比如: // 原数组是一个"三维" ...

  7. 前端开发:Javascript中的数组,常用方法解析

    前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ...

  8. JavaScript 基础回顾——数组

    JavaScript是无类型语言,数组元素可以具有任意的数据类型,同一个数组的不同元素可以具有不同类型.数组的元素设置可以包含其他数组,便于模拟创建多维数组. 1.创建数组 在JavaScript中, ...

  9. javascript里面的数组,json对象,动态添加,修改,删除示例

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

随机推荐

  1. ajax传输中文乱码解决方法

    问题描述: 我是在一个jsp页面有一个保存按钮,点击时会触发saveForm()的js函数,在saveForm()函数里经过校验后,会通过ajax发送数据请求,这样就不用通过提交表单来传输数据了,aj ...

  2. 代码质量管理工具——SonarQube

    写在前面 SonarQube(简称Sonar)是管理代码质量的开放平台,它可以快速地对代码质量进行分析,并给出合理的解决方案,提高管理效率,保证代码质量. SonarQube的流行,在于以下几点: 开 ...

  3. yii2 解决POST 400错误

    第一种解决办法是关闭Csrf public function init(){ $this->enableCsrfValidation = false; } 第二种解决办法是在form表单中加入隐 ...

  4. asp.net三层架构 及其中使用泛型获取实体数据介绍

    asp.net中使用泛型获取实体数据可以发挥更高的效率,代码简洁方便,本例采用三层架构.首先在model层中定义StuInfo实体,然后在 DAL层的SQLHelper数据操作类中定义list< ...

  5. windows安装redis

    下载安装包,由于redis不提供windows版本,但是通过官网了解,如下: The Redis project does not officially support Windows. Howeve ...

  6. 简单的C语言文法

    <程序>→<外部声明>|<程序><外部声明> <外部声明>→<函数定义>|<声明> <函数定义>→< ...

  7. [BZOJ1251]序列终结者

    [BZOJ1251]序列终结者 试题描述 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题 ...

  8. 手机站使图片高度统一jq代码

    <script> function showImg(){ $(".honor_i_c img").each(function(index, element) { var ...

  9. c/c++中关于sizeof、strlen的使用说明

    sizeof: 一般指类型.变量等占用的内存大小(由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小) strlen: c字符串的长度(参数必须是字符型指针 char*,当数组名作 ...

  10. canvas简介

    一.canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 <canvas></canvas> 英 ['kænvəs] 美 ['kænvəs] 帆 ...