js之数组降维且flat源码(百度面试)

本文探讨了JavaScript中将多维数组降维的四种方法,包括使用flat方法,join+split方法,递归以及使用Map。重点解析了源码实现,包括简单实现和在forEach基础上增加类型校验的完善版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们待会些flat源码,先分析下数据降维我们怎么去处理?

法一 用flat方法

let ary = [1, [2, [3, [4, 5]]], 6,{name:1}];
console.log(ary.flat(Infinity))  // flat不会改变原来数组

法二: 用join+splite方法 (只针对基本数据类型)

let ary = [1, [2, [3, [4, 5]]], 6, 'sss'];
console.log(ary.join(',').splite(','))  // flat不会改变原来数组

法三: 用递归+reduce方法

function flatten(ary) {
  return ary.reduce((pre, cur) => {
  return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
  },[])
  }
let ary = [1, 2, [3, 4], [5, [6, 7]]]
flatten(ary)

法四: 用concat方法

let ary = [1, 2, [3, 4], [5, [6, 7]]]
while (ary.some(Array.isArray)) {
  ary = [].concat(...ary);  // concat会改变原来数组
}
console.log(ary)

当然还可以用传统递归的方法写,我觉得比较low,所以直接上flat的源码部分

核心:源码来了

注意:Infinity表示的无穷打的是一个数

1、简单实现

Array.prototype.myFlat = function(deep = 1) {
  let arr = this
  return deep > 0 ? arr.reduce((prev, next) => {
   return (prev.concat(Array.isArray(next) ? next.flat(deep - 1) : next))
  },[]) : arr
}
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
console.log(arr1.myFlat());

2、用forEach简单实现

// forEach 遍历数组会自动跳过空元素
const eachFlat = (arr = [], depth = 1) => {
  const result = []; // 缓存递归结果
  // 开始递归
  (function flat(arr, depth) {
    // forEach 会自动去除数组空位
    arr.forEach((item) => {
      // 控制递归深度
      if (Array.isArray(item) && depth > 0) {
        // 递归数组
        flat(item, depth - 1)
      } else {
        // 缓存元素
        result.push(item)
      }
    })
  })(arr, depth)
  // 返回递归结果
  return result;
} 

3、用for of简单实现

// for of 循环不能去除数组空位,需要手动去除
const forFlat = (arr = [], depth = 1) => {
  const result = [];
  (function flat(arr, depth) {
    for (let item of arr) {
      if (Array.isArray(item) && depth > 0) {
        flat(item, depth - 1)
      } else {
        // 去除空元素,添加非undefined元素(使用void 0比使用undefined能够减少3个字节)
        item !== void 0 && result.push(item);
      }
    }
  })(arr, depth)
  return result;
}

4、在forEach基础上增加增加类型校验(完善下)

		let arr = [1, [2, 3, [4, 5, [12, 3, "zs"], 7, [8, 9, [10, 11, [1, 2, [3, 4]]]]]]];

        //万能的类型检测方法
        const checkType = (arr) => {
            return Object.prototype.toString.call(arr).slice(8, -1);
        }
        //自定义flat方法,注意:不可以使用箭头函数,使用后内部的this会指向window
        Array.prototype.myFlat = function (num) {
            //判断第一层数组的类型
            let type = checkType(this);
            //创建一个新数组,用于保存拆分后的数组
            let result = [];
            //若当前对象非数组则返回undefined
            if (!Object.is(type, "Array")) {
                return;
            }
            //遍历所有子元素并判断类型,若为数组则继续递归,若不为数组则直接加入新数组
            this.forEach((item) => {
                let cellType = checkType(item);
                if (Object.is(cellType, "Array")) {
                    //形参num,表示当前需要拆分多少层数组,传入Infinity则将多维直接降为一维
                    num--;
                    if (num < 0) {
                        let newArr = result.push(item);
                        return newArr;
                    }
                    //使用三点运算符解构,递归函数返回的数组,并加入新数组
                    result.push(...item.myFlat(num));
                } else {
                    result.push(item);
                }
            })
            return result;
        }

        console.log(arr.myFlat(Infinity)); //[1, 2, 3, 4, 5, 12, 3, "zs", 7, 8, 9, 10, 11, 1, 2, 3, 4];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值