参照父对象展平嵌套对象

时间:2018-11-12 03:56:02

标签: javascript recursion functional-programming

我想整理以下内容

let o = {
  name: "John",
  school: {
    name: "Phillps",
  }
};

收件人:

{
  name: "John",
  schoolName: "Phillps"
}

我的代码如下

f= Object.assign({}, ..._flatten(o));

function _flatten(o) {
  return [].concat(
    ...Object.keys(o).map(k =>
      typeof o[k] === "object" ? _flatten(o[k]) : { [k]: o[k] }
    )
  );
}

这产生

{  
 name: "Phillps"
}

如您所见,它不能处理嵌套对象中属性名称的冲突。即学生的名字被学校的名字覆盖了。是否可以修改代码,以便将深色属性以其父对象名称作为前缀?

2 个答案:

答案 0 :(得分:1)

您可以使用Object.entriesArray.prototype.flatMapObject.fromEntries

const upperFirst = (str = "") =>
  str[0] .toUpperCase () + str.substr(1)

const camelCase = ([ first = "", ...rest ]) =>
  first + rest .map (upperFirst) .join ('')

const append = (xs, x) =>
  xs .concat ([ x ])
  
const flatten = (o = {}) =>
{ const loop = (o, path) =>
    Object (o) === o
      ?  Object .entries (o) .flatMap
           ( ([ k, v ]) =>
               loop
                 ( v
                 , append (path, k)
                 )
           )
      : [ [ camelCase (path), o ] ]
  return Object .fromEntries (loop (o, []))
}

console.log
  ( flatten
      ( { name: "John"
        , school:
            { name: "Phillips"
            , district: { zone: 1 }
            }
        }
      )
  )
  
// { "name": "John"
// , "schoolName": "Phillips"
// , "schoolDistrictZone": 1
// }

flatMap急切地评估输入并在flatten返回之前创建一些中间值。因为Object.fromEntries接受任何迭代,所以最好用生成器编写loop

const flatten = (o = {}) =>
{ const loop = function* (o, path)
  { if (Object (o) === o)
      for (const [ k, v ] of Object .entries (o))
        yield* loop
          ( v
          , append (path, k)
          )
    else
      yield [ camelCase (path), o ]
  }
  return Object .fromEntries (loop (o, []))
}

重新运行该程序,您将看到完全相同的输出。还值得一提的是两个程序之间的结构相似性。

答案 1 :(得分:0)

您可以使用相同的代码,只需将前缀作为参数传递给_flatten()。求助时,将前缀与当前父键连接起来。随着嵌套的深入,这将继续添加前缀:

function _flatten(o, prefix="") {
  return [].concat(
    ...Object.keys(o).map(k =>
            typeof o[k] === "object" ? _flatten(o[k], prefix+k) : { [prefix+k]: o[k] }
    )
  );
}

let o = {
    name: "John",
    school: {
      name: "Phillps",
    }
  };

f= Object.assign({}, ..._flatten(o));

console.log(f)

此外,您可以简单地使用reduce()Object.assign编写一些代码,而不用[].concact()创建数组

function _flatten(o, prefix = "") {
  return Object.keys(o).reduce((obj, k) =>
    Object.assign(obj, typeof o[k] === "object" 
        ? _flatten(o[k], prefix + k) 
        : { [prefix + k]: o[k]})
     , {})
}

let o = {
  name: "John",
  school: {
    name: "Phillps",
  }
};

f = _flatten(o);

console.log(f)