javascript复杂对象扁平化(最简手撕)

179 阅读1分钟

来看道编程题目,你能在10分钟内写完吗?

/**
 * 编程题:对象扁平化
 * 说明:请实现 flatten(input) 函数,input 为一个 javascript 对象(Object 或者 Array)
 * 返回值:扁平化后的结果。
 * 示例:
 *   var input = {
 *     a: 1,
 *     b: [ 1, 2, { c: true }, [ 3 ] ],
 *     d: { e: 2, f: 3 },
 *     g: null, 
 *   }
 *   var output = flatten(input);
 *   output如下
 *   {
 *     "a": 1,
 *     "b[0]": 1,
 *     "b[1]": 2,
 *     "b[2].c": true,
 *     "b[3][0]": 3,
 *     "d.e": 2,
 *     "d.f": 3,
 *     // "g": null,  值为null或者undefined,丢弃
 *  }
 */

解题思路

入参:一个复杂对象obj

出参:一个扁平化处理后的对象result

递归:因为对象value属性不确定是 obj 还是 array,需要递归遍历对象的 value

注意:key值拼接时,第一次需要取原对象的key值

代码实现

var input = {
  a: 1,
  b: [ 1, 2, { c: true }, [ 3 ] ],
  d: { e: 2, f: 3 },
  g: null, 
  e: {j: 222, k: [1, 2, 3, {a: null, d: 32}]},
  f: undefined,
  h: '',
  josie: 'so cool'
}

function flatten(obj) {
  let result = {}
  handleData(obj, null)
  function handleData(flatData, key) {
    const isArray = Array.isArray(flatData)
    // 对象转换成以key为数组形式进行遍历(为了共用一个循环..)
    let data = isArray ? flatData : Object.keys(flatData)
    data.forEach((item, index) => {
      const dataValue = isArray ? item : flatData[item]
      // 无效数据过滤(null,undefined)
      if (!dataValue) return
      // key值拼接,注意第一次遍历为null取原对象的key
      const keyStr = !key ? item : (key + (isArray ? `[${index}]` : `.${item}`))
      // 判断当前子元素是否是对象or数组,进行递归
      if (dataValue instanceof Object) {
        handleData(dataValue, keyStr)
      } else {
        result[keyStr] = dataValue
      }
    })
  }
  return result
}
console.log(flatten(input))

/** 运行结果
{
    "a": 1,
    "b[0]": 1,
    "b[1]": 2,
    "b[2].c": true,
    "b[3][0]": 3,
    "d.e": 2,
    "d.f": 3,
    "e.j": 222,
    "e.k[0]": 1,
    "e.k[1]": 2,
    "e.k[2]": 3,
    "e.k[3].d": 32,
    "josie": "so cool"
}
**/