【问题标题】:Merging an array of objects without overwriting合并对象数组而不覆盖
【发布时间】:2019-02-04 15:19:57
【问题描述】:

我目前使用一些 JSON,它必须以树状层次结构构建。层次的深度变化很大,因此是未知的。

就像现在一样,我已经获得了一个对象数组。示例如下。

[
    {
      "name": "level1",
      "collapsed": true,
      "children": [
        {
          "name": "Level 1 item here",
          "id": 360082134191
        }
      ]
    },
    {
      "name": "level1",
      "collapsed": true,
      "children": [
        {
          "name": "level2",
          "collapsed": true,
          "children": [
            {
              "name": "Level 2 item here",
              "id": 360082134751
            }
          ]
        }
      ]
    },
    {
      "name": "level1",
      "collapsed": true,
      "children": [
        {
          "name": "Another level 1 item",
          "id": 360082262772
        }
      ]
    }
  ]

我想要实现的是这些对象被合并,而不覆盖或替换任何东西。下面列出了我希望如何格式化数据的示例:

[
  {
    "name": "level1",
    "collapsed": true,
    "children": [
      {
        "name": "level2",
        "collapsed": true,
        "children": [
          {
            "name": "Level 2 item here",
            "id": 360082134751
          }
        ]
      },
      {
        "name": "Level 1 item here",
        "id": 360082134191
      },
      {
        "name": "Another level 1 item",
        "id": 360082262772
      }
    ]
  }
]

如何使用 JavaScript 实现这一点?没有库是首选,但是可以使用 ES6。

编辑: 输出是一个数组很重要,因为没有子项的项可以出现在根目录。

【问题讨论】:

  • 为什么"Level 1 item here" 比"level2" 来得晚?
  • 欢迎来到 Stack Overflow!请拨打tour,访问help center,并阅读asking good questions。在做了一些研究并searching 了解 SO 的相关主题之后,自己尝试一下。如果您遇到困难,请发布您的尝试Minimal, Complete, and Verifiable example,并准确记录您卡在哪里。人们会很乐意提供帮助。
  • 我假设您正在合并 name。如果您尝试合并的节点具有不同的 collapsed 值,您会期待什么?
  • @ScottSauyet 这不是问题,因为这是初始结构,因此它总是错误的! :-)

标签: javascript json ecmascript-6 treeview


【解决方案1】:

我假设您在处理数据方面需要一点帮助。可能有多种方法可以实现这一点,这是我该怎么做。

// data => supplied data
const result = data.reduce ((acc, item) => {
  // if acc array already contains an object with same name,
  // as current element [item], merfe the children
  let existingItem;

  // Using a for loop here to create a reference to the
  // existing item, so it'd update this item when childrens
  // will be merged.
  for (let index = 0; index < acc.length; index ++) {
    if (acc[index].name === item.name) {
      existingItem = acc[index];
      break;
    }
  }
  // if existingItem exists, merge children of
  // existing item and current item.
  // else push it into the accumulator
  if (existingItem) {
    existingItem.children = existingItem.children.concat(item.children);
  } else {
    acc.push (item);
  }
  return acc;
}, []);

【讨论】:

  • 这会在reduce 中运行不必要的loop 和if 条件
  • 是的,我明白你的意思,但更容易理解。一旦有了步骤和逻辑,就可以进行代码优化。这个想法是让某人了解如何接近。我在回答中已经说过,可能有多种方法可以实现这一点。
  • @adiga 你能解释一下你将如何重构这段代码吗?我目前正在处理深度嵌套的对象。
【解决方案2】:

我假设您想根据级别 1 对象中的 name 属性进行分组。你可以像这样做一个简单的reduce 和Object.values:

const input = [{"name":"level1","collapsed":true,"children":[{"name":"Level 1 item here","id":360082134191}]},{"name":"level1","collapsed":true,"children":[{"name":"level2","collapsed":true,"children":[{"name":"Level 2 item here","id":360082134751}]}]},{"name":"level1","collapsed":true,"children":[{"name":"Another level 1 item","id":360082262772}]}]
  
const merged = input.reduce((r,{name, collapsed, children}) =>{
    r[name] = r[name] || {name, collapsed, children:[]};
    r[name]["children"].push(...children)
    return r;
}, {})
  
const final = Object.values(merged);
console.log(final)

你可以在一行中完成所有事情:

const input = [{"name":"level1","collapsed":true,"children":[{"name":"Level 1 item here","id":360082134191}]},{"name":"level1","collapsed":true,"children":[{"name":"level2","collapsed":true,"children":[{"name":"Level 2 item here","id":360082134751}]}]},{"name":"level1","collapsed":true,"children":[{"name":"Another level 1 item","id":360082262772}]}]

const output = Object.values(input.reduce((r,{name,collapsed,children}) => (
    (r[name] = r[name] || {name,collapsed,children: []})["children"].push(...children), r), {}))
console.log(output)

【讨论】:

    猜你喜欢
    • 2011-11-24
    • 2017-11-27
    • 2014-01-02
    • 2020-04-21
    • 2017-09-22
    • 2018-04-22
    • 2013-07-11
    • 1970-01-01
    • 2018-05-13
    相关资源
    最近更新 更多