【问题标题】:Flattening nested objects with reference to parent object参照父对象展平嵌套对象
【发布时间】:2019-04-14 19:06:49
【问题描述】:

我想把下面的东西弄平

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"
}

如您所见,它无法处理嵌套对象中的属性名称冲突。 IE。学生的名字被我学校的名字覆盖了。是否可以修改代码,使深层属性以它们的父对象名称为前缀?

【问题讨论】:

    标签: javascript recursion functional-programming


    【解决方案1】:

    您可以使用相同的代码,只需将前缀作为参数传递给_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)

    【讨论】:

      【解决方案2】:

      您可以使用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, []))
      }
      

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

      【讨论】:

        猜你喜欢
        • 2021-06-09
        • 2018-10-24
        • 2017-07-02
        • 2020-12-22
        • 2021-03-22
        • 2021-10-19
        • 2020-06-23
        • 2012-05-29
        • 2017-10-19
        相关资源
        最近更新 更多