JS专题之数组展开

前言

首先什么是数组展开?
假如现在有这样一个需求:将后台的一个多重 List 数据,展开成一个 List 后,并去重后排序;

["a", "b", ["c", "d"], [["d"],"e"], "f"] => ["a", "b", "c", "d", "e"];
复制代码

数组去重我们前面在《JS专题之数组去重》已经讲过了,那么前一步的多重数组展开成单层数组,该如何处理呢?

这就来到我们所要探讨的数组展开了。
根据需求的特点,数组展开需要进行迭代和递归。

回答文章开头的问题:

将多重数组转化成单层数组的过程就是数组展开,也叫作数组扁平化(flatten)

一、循环加递归

最简单的思路:循环中判断,如果子元素是数组则递归。

function flatten(origin) {
    var result = [];
    for(var i = 0; i< origin.length; i++) {
        var item = origin[i];
        if(Array.isArray(item)) {
            result = result.concat(flatten(item))
        } else {
            result.push(item);
        }
    }
    return result;
}

var arr = ["a", "b", ["c", "d"], [["d"],"e"], "f"];
flatten(arr);  // ["a", "b", "c", "d", "d", "e", "f"]
复制代码
二、toString()

数组的原型对象上有一个方法,toString, 它能把数组的所以元素转化成用逗号隔开的字符串。

var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];  
arr.toString()  // "1,2,3,4,a,b,c,d,d,e,f"

// 所以,利用 split 先把字符串转化为单层数组,再进行处理。
const flatten = (origin) => origin.toString().split(',');  // ["1", "2", "3", "4", "a", "b", "c", "d", "d", "e", "f"]
复制代码

由于 toString 转化为字符串的时候,不会区分字符串和数字类型,在进行区分数据类型的时候要注意。

三、split

上面的方法,我们用 toString() 将数组转化为字符串,那么我们也可以用 split 来做:

var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
function flatten(arr) {
    return arr.join(',').split(',');  
} 
console.log(flatten(arr))。 // ["1", "2", "3", "4", "a", "b", "c", "d", "d", "e", "f"]
复制代码

同样,这种字符串和数组互转的过程,不适合多种数据类型同时处理。

四、reduce

我们注意到其实数组扁平化其实就是“迭代 + 拼接(累加) + 递归”的过程,数组 reduce 方法既可以迭代又可以累加,适合做数组扁平化。

function flatten(origin){
  return origin.reduce(function(init, item){
    return init.concat(Array.isArray(item) ? flatten(item) : item)
  }, [])
}
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];  
console.log(flatten(arr)) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"]
复制代码
五、some + concat

some 会遍历数组的每一个元素,判断是否有元素都满足条件,最后返回布尔值。some 一旦返回真值后,其后的元素就不会继续监测。

function flatten(origin) {
    while (origin.some(item => Array.isArray(item))){
    origin = [].concat.apply([], origin);
  }
  return origin;
}
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];  
console.log(flatten(arr)) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"]
复制代码
六、some + 扩展运算符

ES6 扩展运算符...可以将两重数组转换为单层数组:

[].concat(...[1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"]);  // [1, 2, 3, Array(1), "a", "b", "c", "d", Array(1), "e", "f"]

// 利用 some 方法,我们可以实现多重转换为单层:

function flatten(origin) { while(origin.some(item=> Array.isArray(item))) {
        origin = [].concat(origin);
    } return origin;
}

var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];  
console.log(flatten(arr)) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"]
复制代码
七、原生 flat

JS Array 对象提供了原生的可以实现扁平化的函数flat:详细说明见 MDN

var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
// 2 表示深度
arr.flat(2)  // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"];

复制代码
总结

数组扁平化其实就是利用元素迭代 + 元素拼接(叠加)+ 递归调用来对数组进行处理,达到将多层数组转换为单层数组的过程。 欢迎关注我的个人公众号“谢南波”,专注分享原创文章。

掘金专栏 JavaScript 系列文章
  1. JavaScript之变量及作用域
  2. JavaScript之声明提升
  3. JavaScript之执行上下文
  4. JavaScript之变量对象
  5. JavaScript之原型与原型链
  6. JavaScript之作用域链
  7. JavaScript之闭包
  8. JavaScript之this
  9. JavaScript之arguments
  10. JavaScript之按值传递
  11. JavaScript之例题中彻底理解this
  12. JavaScript专题之模拟实现call和apply
  13. JavaScript专题之模拟实现bind
  14. JavaScript专题之模拟实现new
  15. JS专题之事件模型
  16. JS专题之事件循环
  17. JS专题之去抖函数
  18. JS专题之节流函数
  19. JS专题之函数柯里化
  20. JS专题之数组去重
  21. JS专题之深浅拷贝
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值