【算法】对象扁平化

70 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

通过这篇文章,我们已经知道如何将一个数组进行扁平化了,在这篇文章里,我就准备聊聊如何去实现 对象的扁平化,废话不多说,开搞!

ppx2.jpg

正文

先给出题目

需要被铺平的对象
{
    a: 1,
    b: '2',
    c: ()=>{},
    d: undefined,
    e: {
        f: {
            g: 1
        }
    },
    h: {},
    i: [],
    j: [1,{k:2}],
    l: [[]],
    m: {
        n: {}
    }
}

铺平后
{
    a: 1,
    b: '2',
    c: ()=>{},
    d: undefined,
    'e.f.g':1,
    h: {},
    i: {},
    'j[0]': 1,
    'j[1].k': 2,
    'l[0]': [],
    'm.n': {}
}

看到这个题目,我们进行分析后,可以得知以下几点的信息

  1. 对于 非对象且非数组类型 的属性值,是最终用来进行赋值给铺平后的对象的
  2. 对于 空数组或空对象,直接使用其值,不再进行铺平
  3. 对于 非空数组,进行铺平处理
  4. 对于 非空对象,进行铺平处理

铺平处理其实就是一个 递归过程,终止条件就是下面两种

  1. 值为非数组且非对象
  2. 值为空数组或空对象

结合上述分析,下面给出代码

function flat(obj) {
    const res = {}
    
    function recursion(k,v) {
        if(!/Object|Array/.test(Object.prototype.toString.call(v))) {
            res[k] = v
        }else if(Array.isArray(v)) {
            if(!v.length) {
                res[k] = []
                return 
            }
            v.forEach((item,index)=>{
                recursion(`${k}[${index}]`,item)
            })
        }else {
            const keys = Object.keys(v)
            if(!keys.length) {
                res[k] = {}
                return
            }
            keys.forEach(item=>{
                recursion(k ? `${k}.${item}` : item, v[item])
            })
        }
    }
    
    recursion('',obj)
    return res
}

简单对上述代码进行分析

  1. 定义一个 res对象,用于保存被铺平后的属性

  2. 定义一个递归函数 recursion,用于铺平,接受 kv 两个参数,然后对 v 进行类型判断

    • 如果v是 非数组且非对象,那么就将v跟对应的k组合起来
    • 如果是 数组,首先判断 是否为空,如果是,就直接将k与v组合起来,如果不是,就遍历数组的每一项,并将k设置为 ${k}[${index}],用于下一轮的递归
    • 如果是对象,首先用 Object.keys 获取所有的键,然后判断是否为空对象,如果是,就直接将k与v组合起来,如果不是,就遍历keys数组,然后将k设为 (k ? `k.{k}.{item}` : item,用于下一轮的递归,需要说明的是,k为空,表示当前是 根属性,不需要前缀
  3. 调用递归函数,需要注意的是,需要将k参数设为 空字符串,表明是 根属性

  4. 返回res对象

666.jpg