Javascript实现的数组降维——维度不同,怎么谈恋爱(修订版)
数组的元素可能是数组,这样一层层嵌套,可能得到一个嵌套很深的数组,数组降维要做的事就是把嵌套很深的数组展开,一般最后得到一个一维数组,其中的元素都是非数组元素,比如数组[1, [2, 3, [4, 5], 6], 7, 8]降维展开后是[1, 2, 3, 4, 5, 6, 7, 8].
1.普通方法
function flattenMd(arr){
    var result=[]
    function flatten(arr){
        for (var i = 0; i < arr.length; i++) {
            if (Array.isArray(arr[i])) {
                flatten(arr[i]);
            }else{
                result.push(arr[i]);
            }
        }
    }
    flatten(arr);
    return result;
}
var arr=[1, [2, 3, [4, 5], 6], 7, 8]
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方法位于内部。还可以改造成闭包的形式
function flattenMd(ret) {
    function flatten(arr) {
        arr.forEach(function(item) {
            (Array.isArray(item)) ? flatten(item) : ret.push(item);
        });
    }
    return function(arr) {
        flatten(arr);
        return ret;
    }
}([]);
var arr=[1, [2, 3, [4, 5], 6], 7, 8]
console.log(flattenMd(arr));[ 1, 2, 3, 4, 5, 6, 7, 8 ]
2.数组concat方法
熟悉数组操作方法的开发人员应该知道数组concat方法的特性:传递给concat方法的参数序列中如果包含数组,则会将这个数组的每一项添加到结果数组中,这就使数组的这个方法具有了天然的展开二维数组的能力,比如:
var colors=['red','green','blue'];
var colors2=colors.concat('yellow',['black','brown']);
console.log(colors2)//[ 'red', 'green', 'blue', 'yellow', 'black', 'brown' ]
需要注意的是如果数组的元素还是数组则不会再展开了,也就是concat方法只能降低一维。借助concat方法,可以得到另一种二维数组降维方法。
function flatten2d(arr) {
    var result = [];
    for(var i = 0; i < arr.length; i++) {
        result = result.concat(arr[i]);
    }
    return result;
}
上面的方法还可以进一步简化。我们知道apply方法是可以直接接受数组参数,这样我们连循环迭代都省了。
function flatten2d(arr) {
    return Array.prototype.concat.apply([], arr);
}
网上很多博客说使用递归很容易将二维的降维改造成多维的降维,实际上操作起来是比较复杂的,因为没有现成的方法能够判断某个数组是不是二维数组,也就不能判断递归的结束条件了。所以对于多维数组的降维需要重新规划使用concat方法可以避免方法一中多出的内部函数
对于多维数组
function flattenMd(arr) {
    var result = [];
    for(var i = 0; i < arr.length; i++){
        if(arr[i] instanceof Array) {
            result = result.concat(flattenMd(arr[i]));
        }
        else {
            result.push(arr[i]);
        }
    }
    return result;
}
var arr=[1, [2, 3, [4, 5], 6], 7, 8]
console.log(flattenMd(arr));[ 1, 2, 3, 4, 5, 6, 7, 8 ]
3.数组join和split方法的结合(有缺陷)
很多开发人员都知道数组的join方法可以将数组展开成字符串,但是不确定的是join方法能够展平数组,即使是多维数组,我们再使用split方法重新组合数组就行了。但是这个方法有天然缺陷,下面的例子中会看到
function flattenMd(arr) {
   return arr.join().split(',');
}
var arr=['1', [null, 3, [4, 5], {K:1}], undefined, 8]
console.log(flattenMd(arr));//[ '1', '', '3', '4', '5', '[object Object]', '', '8' ]
从结果可以看出,这样处理过后有几个缺点:一是所有类型的元素都会变成字符串;二是null、undefined会变成空字符串、对象会变成'[object Object]'。相当于调用了toString方法,当也不是说这个方法一无是处。对于同一种类型的元素,还是很有用处的,比如要求多维数组的最大值。
function flattenMd(arr) {
   return arr.join().split(',');
}
var arr=[1, [5, 3, [8, 5], 5,[15]], 9, 13]
console.log(Math.max.apply(null,flattenMd(arr)));//15
4.最佳实践方法
function flatten(arr) {
    return arr.reduce((prev, cur) => {
        return plane.concat(Array.isArray(cur) ? flatten(cur) : cur);
    }, []);
}
function deepFlatten(arr) {
    flatten = arr => [].concat(...arr);
    return flatten(arr.map(item => (Array.isArray(item) ? deepFlatten(item) : item)));
}
参考
优雅的数组降维——Javascript中apply方法的妙用
Javascript实现的数组降维——维度不同,怎么谈恋爱(修订版)的更多相关文章
- Javascript实现的数组降维——维度不同,怎么谈恋爱
		数组的元素可能是数组,这样一层层嵌套,可能得到一个嵌套很深的数组,数组降维要做的事就是把嵌套很深的数组展开,一般最后得到一个一维数组,其中的元素都是非数组元素,比如数组[1, [2, 3, [4, 5 ... 
- 优雅的数组降维——Javascript中apply方法的妙用
		将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转换.本文将从朴素的循环转换开始,逐一介绍三 ... 
- 数组降维-JavaScript中apply方法妙用
		海纳百川,有容乃大 1.普通循环转换方式 将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转 ... 
- JavaScript学习笔记——数组
		javascript数组数组是一个可以存储 一组 或是 一系列 相关数据 的 容器. 一.为什么要使用数组. (1)为了解决大量相关数据的存储和使用的问题. (2)模拟真是的世界. 二.如何创建数组 ... 
- php中使用array_reduce给数组降维
		PHP里面最强大的工具,就是数组,它融合了多种数据结构的特点,数组.队列.栈.哈希表等等,而且容器可以兼容各种类型,任意嵌套,简直无所不能.围绕着数组,PHP原生支持了一些列的函数,使得数组在实际编程 ... 
- 面试官:JavaScript如何实现数组拍平(扁平化)方法?
		面试官:JavaScript如何实现数组拍平(扁平化)方法? 1 什么叫数组拍平? 概念很简单,意思是将一个"多维"数组降维,比如: // 原数组是一个"三维" ... 
- 前端开发:Javascript中的数组,常用方法解析
		前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ... 
- JavaScript 基础回顾——数组
		JavaScript是无类型语言,数组元素可以具有任意的数据类型,同一个数组的不同元素可以具有不同类型.数组的元素设置可以包含其他数组,便于模拟创建多维数组. 1.创建数组 在JavaScript中, ... 
- javascript里面的数组,json对象,动态添加,修改,删除示例
		<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ... 
随机推荐
- 第六十三天 js基础
			一.JS三个组成部分 ES:ECMAScript语法 DOM:document对象模型=>通过js代码与页面文档(出现在body中的所有可视化标签)进行交互 BOM:borwser对象模型=&g ... 
- Python 正则处理_re模块
			正则表达式 动机 文本处理成为计算机常见工作之一 对文本内容搜索,定位,提取是逻辑比较复杂的工作 为了快速方便的解决上述问题,产生了正则表达式技术 定义 文本的高级匹配模式, 提供搜索, 替换, 本质 ... 
- java String转int int转化为String
			String转int String str = "123"; int a = Integer.parseInt(str); System.out.println(a); Integ ... 
- Oracle 获取前几行数据问题的陷阱
			查询用户数据表,需要根据时间正序排序,然后获取时间最早的前三条数据,是不是第一印象想这么写: select * from users where rownum<4 order by datati ... 
- python 发送post和get请求
			摘自:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201231085444250/ 测试用CGI,名字为test.py,放在ap ... 
- org.hibernate.ObjectNotFoundException: No row with the given identifier exists解决办法
			hibernate-取消关联外键引用数据丢失抛异常的设置@NotFound hibernate项目里面配了很多many-to-one的关联,后台在查询数据时已经作了健全性判断,但还是经常抛出对象找不到 ... 
- Client-Side Template Injection with AngularJS
			<html> <head> <meta charset="utf-8"> <script src="https://cdn.bo ... 
- spark JAVA 开发环境搭建及远程调试
			spark JAVA 开发环境搭建及远程调试 以后要在项目中使用Spark 用户昵称文本做一下聚类分析,找出一些违规的昵称信息.以前折腾过Hadoop,于是看了下Spark官网的文档以及 github ... 
- luogu 4345 Lucas的变形应用
			求 sigma i由0-k C(n,i) 利用Lucas定理+整除分块将C(n/p,i/p)利用i/p分块,得到k/p-1个整块(p-1)和一个小块(k%p) 最后得到式子 F(n,k)=F(n/p, ... 
- mui-选项卡+scroll滚动
			详细操作见代码: <!doctype html> <html> <head> <meta charset="UTF-8"> < ... 
