前端咖如何扁平化数组或对象

扁平化数组或对象,请设计一个flat,实际工作中经常碰到,面试也常常会遇到这种面试题,所以接下来咱们一起详细分析如何实现这个flat的具体步骤。

数组flat

将多维数组转换成一维数组,例如:['a', ['b', 'c', ['d', 'e', 'f', ['g']]]]转成['a', 'b', 'c', 'd', 'e', 'f', 'g']。如何实现flat函数?

方法一、递归

「步骤:」

  1. 创建一个空的新数组;

  2. 遍历多维数组;

  3. 如果当前元素是非数组,将元素添加到新数组末尾;

  4. 如果当前元素是数组,元素调用函数本身;

  5. 返回新数组。

let arr = ['a', ['b', 'c', ['d', 'e', 'f', ['g']]]];
function flat(array){
    let arr = [];
    array.forEach(item=>{
        if(Array.isArray(item)){
            arr = arr.concat(flat(item));
        }else{
            arr.push(item);
        }
    });
    return arr;
}
flat(arr);

//  => ['a', 'b', 'c', 'd', 'e', 'f', 'g']

方法二、非递归

「步骤:」

  1. 创建一个空的新数组;

  2. 创建一个队列;

  3. 循环遍历队列,每次移除首个元素;

  4. 如果首个元素是非数组,将首个元素添加到新数组开头;

  5. 如果首个元素是数组,将首个元素添加到队列的末尾;

  6. 返回新数组。

let arr = ['a', ['b', 'c', ['d', 'e', 'f', ['g']]]];
function flat(array){
    let arr = [];
    let queue = array;
    if(!queue.length){
        return [];
    }
    while(queue.length){
        let val = queue.pop();
        if(Array.isArray(val)){
            queue.push(...val);
        }else{
            arr.unshift(val);
        }
    }
    return arr;
}
flat(arr);

//  => ['a', 'b', 'c', 'd', 'e', 'f', 'g']

对象flat

如果是对象又如何处理呢,例如:{a:{b:{c:{d:'qdkabcd'}},d:{x: 'qdkadx'},e:'qdkae'}}转成{'a.e':'qdkae','a.d.x':'qdkadx','a.b.c.d':'qdkabcd'}

方法一、递归

「步骤:」

  1. 创建一个空新对象;

  2. 遍历对象属性;

  3. 如果当前属性是基本类型,将属性及值复制到新对象上;

  4. 如果当前属性是引用类型,将属性及值递归调用函数本身;

  5. 返回新对象。

let object = {
    a: {
        b: {
            c: {
                d: 'qdkabcd'
            }
        },
        d: {
            x: 'qdkadx'
        },
        e: 'qdkae'
    }
};
function flat(object, prefix){
    let res = {};
    Object.entries(object).forEach(item=>{
        let [k, v] = item;
        let key = prefix?`${prefix}.${k}`:k;
        if(typeof v!= 'object'){
            res[key] = v;
        }else{
            res = Object.assign(res, flat(v, key));
        }
    });
    return res;
}
flat(object);

/*
{
    'a.b.c.d': 'qdkabcd',
    'a.d.x': 'qdkadx',
    'a.e': 'qdkae'
}
*/

方法二:非递归

「步骤:」

  1. 创建一个空新对象;

  2. 创建一个队列;

  3. 循环遍历队列,每次移除首个元素键值对数组;

  4. 如果首个元素键值对数组的值是基本类型,将键及值复制到新对象上;

  5. 如果首个元素键值对数组的值是引用类型,将键及值添加到队列的末尾;

  6. 返回新对象。

let object = {
    a: {
        b: {
            c: {
                d: 'qdkabcd'
            }
        },
        d: {
            x: 'qdkadx'
        },
        e: 'qdkae'
    }
};
function flat(object){
    let res = {};
    let queue = Object.entries(object);
    while(queue.length){
        let [key, obj] = queue.pop();
        Object.entries(obj).forEach(item=>{
            let [k, v] = item;
            if(typeof v!= 'object'){
                res[`${key}.${k}`] = v;
            }else{
                queue.push([`${key}.${k}`, v]);
            }
        });
    }
    return res;
}
flat(object);

/*
{
    'a.e': 'qdkae',
    'a.d.x': 'qdkadx',
    'a.b.c.d': 'qdkabcd'
}
*/

总结

递归是指直接或间接调用函数本身,也成为线性递归。特点:代码精炼,易于阅读,性能差。非递归是指借助堆栈或者循环算法实现。代码复杂,不易理解,性能好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值