【问题标题】:Make object as child according to the Parent Id JavaScript [duplicate]根据父 ID JavaScript 将对象设为子对象 [重复]
【发布时间】:2019-10-21 18:30:57
【问题描述】:

我有以下来自API的数据:

[
  {
    "Code": "01002",
    "ParentAccountId": "01",
  },
  {
    "Code": "01001001003",
    "ParentAccountId": "01001001",
  },
  {
    "Code": "01001004",
    "ParentAccountId": "01001",
  },
  {
    "Code": "02",
    "ParentAccountId": null,
  },
  {
    "Code": "01002001",
    "ParentAccountId": "01002",
  },
  {
    "Code": "02002",
    "ParentAccountId": "02",
  },
  {
    "Code": "02001",
    "ParentAccountId": "02",
  },
  {
    "Code": "01001001001",
    "ParentAccountId": "01001001",
  },
  {
    "Code": "03",
    "ParentAccountId": null,
  },
  {
    "Code": "01002002",
    "ParentAccountId": "01002",
  },
  {
    "Code": "03001",
    "ParentAccountId": "03",
  },
  {
    "Code": "01",
    "ParentAccountId": null,
  },
  {
    "Code": "01001001002",
    "ParentAccountId": "01001001",
  },
  {
    "Code": "01001002",
    "ParentAccountId": "01001",
  },
  {
    "Code": "01001001",
    "ParentAccountId": "01001",
  },
  {
    "Code": "01001003",
    "ParentAccountId": "01001",
  },
  {
    "Code": "01001005",
    "ParentAccountId": "01001",
  },
  {
    "Code": "01001",
    "ParentAccountId": "01",
  }
]

看看ParentAccountId

由于我需要将其传递给treeview 组件,因此我需要将其转换为如下内容:

    [
  {
    "Code": "01",
    "ParentAccountId": null,
    "children": [
        {
            "Code": "01001",
            "ParentAccountId": "01",
            "children": [
                  {
                    "Code": "01001001",
                    "ParentAccountId": "01001",
                    "children": [
                        {
                            "Code": "01001001001",
                            "ParentAccountId": "01001001",
                            "children": [],
                          },
                        {
                            "Code": "01001001002",
                            "ParentAccountId": "01001001",
                            "children": [],
                          },
                          {
                            "Code": "01001001003",
                            "ParentAccountId": "01001001",
                            "children": [],
                          },
                    ],
                  },
                {
                    "Code": "01001002",
                    "ParentAccountId": "01001",
                    "children": [],
                  },
                  {
                    "Code": "01001003",
                    "ParentAccountId": "01001",
                    "children": [],
                  },
                  {
                    "Code": "01001004",
                    "ParentAccountId": "01001",
                    "children": [],
                  },
                  {
                    "Code": "01001005",
                    "ParentAccountId": "01001",
                    "children": [],
                  }
            ],
          },
        {
            "Code": "01002",
            "ParentAccountId": "01",
            "children": [
                {
                    "Code": "01002001",
                    "ParentAccountId": "01002",
                    "children": [],
                  },
                {
                    "Code": "01002002",
                    "ParentAccountId": "01002",
                    "children": [],
                  },
            ],
          },
    ],
  },
  {
    "Code": "02",
    "ParentAccountId": null,
    "children": [
          {
            "Code": "02001",
            "ParentAccountId": "02",
            "children": [],
          },
        {
            "Code": "02002",
            "ParentAccountId": "02",
            "children": [],
          },
    ],
  },
  {
    "Code": "03",
    "ParentAccountId": null,
    "children": [
        {
            "Code": "03001",
            "ParentAccountId": "03",
            "children": [],
          },
    ],
  },
]

我想根据code 将该对象作为其父对象的子对象。该方案是,如果ParentAccountId 为空,则它是顶级父级,如果ParentAccountId 的长度为2,那么如果ParentAccountId 的长度为5,那么它是第一级子级,那么如果@987654330,它就是第三级子级@ 长度为 8 则为 4 级子级,ParentAccountId 长度为 11 级则为 5 级子级。由于 1 级子级有 2 个长度为 ParentAccountId,那么后续子级将具有 ParentAccountId 作为父级加号的 Code。为了更好地理解,请看第二个,因为我的英语不是那么好。

我对逻辑感到困惑。有什么建议吗?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您可以使用reduce 方法创建树结构来创建递归函数,在每次迭代中检查父 id 是否等于当前元素 id。

    const data = [{"Id":"1","Code":"01","Title":"Account 01","ParentAccountId":null},{"Id":"2","Code":"02","Title":"Account 02","ParentAccountId":null},{"Id":"3","Code":"01001","Title":"Account 01001","ParentAccountId":"01"},{"Id":"4","Code":"01002","Title":"Account 01002","ParentAccountId":"01"},{"Id":"5","Code":"01002001","Title":"Account 01002001","ParentAccountId":"01002"}]
    
    function toTree(data, pid = null) {
      return data.reduce((r, e) => {
        if (e.ParentAccountId == pid) {
          const obj = { ...e };
          const children = toTree(data, e.Code);
          if (children.length) obj.children = children;
          r.push(obj);
        }
        return r;
      }, [])
    }
    
    const result = toTree(data)
    console.log(result)

    【讨论】:

    • 嘿,@nenad 你的函数更好,并且适用于我的多级数据,你能解释一下它的性能不如使用循环吗?如果没有性能问题,我会选择这个解决方案,否则我会选择循环解决方案,因为我有很多数据。
    【解决方案2】:

    所涉及的逻辑是首先尝试找到每个对象的子对象(使用filter 找到所有具有ParentAccountId 等于每个对象Code 的对象)然后过滤数据以仅返回根父母(ParentAccountId 等于 null 的对象)。

    试试下面的代码。

    var data = [{
        "Id": "1",
        "Code": "01",
        "Title": "Account 01",
        "ParentAccountId": null
      },
      {
        "Id": "2",
        "Code": "02",
        "Title": "Account 02",
        "ParentAccountId": null
      },
      {
        "Id": "3",
        "Code": "01001",
        "Title": "Account 01001",
        "ParentAccountId": "01"
      },
      {
        "Id": "4",
        "Code": "01002",
        "Title": "Account 01002",
        "ParentAccountId": "01"
      },
      {
        "Id": "5",
        "Code": "01002001",
        "Title": "Account 01002001",
        "ParentAccountId": "01002"
      }
    ]
    
    rearrangeData = () => {
    
      var newData = []
    
      data.forEach((x) => {
        x['children'] = data.filter((y) => {
          return y.ParentAccountId === x.Code
        })
        var parent = data.find((y) => {
          return y.Code === x.ParentAccountId
        })
        if (parent && parent.children) {
          parent.children.push(x)
        } else if (parent && !parent.children) {
          parent['children'] = [x];
        } else {
          return x
        }
        newData.push(parent)
      })
    
      var parents = newData.filter((x) => {
        return x.ParentAccountId === null
      })
    
      console.log(parents);
    }
    
    rearrangeData()

    【讨论】:

    • 兄弟,它只适用于前两个孩子,检查我已经更新了我代码中的数据,你的代码不适用于该数据。
    • 我编辑了代码 sn-p。现在可以了。您还可以访问 codepen here,因为 sn-p 会切断一些记录的数据。
    【解决方案3】:

    我正在等待工作中的一项任务,所以我想我会为你整理一个实现。并不是说它比链接的线程中的解决方案更好或更差 - 只是另一种实现:

    const data = [{
        "Id": "1",
        "Code": "01",
        "Title": "Account 01",
        "ParentAccountId": null
      },
      {
        "Id": "2",
        "Code": "02",
        "Title": "Account 02",
        "ParentAccountId": null
      },
      {
        "Id": "3",
        "Code": "01001",
        "Title": "Account 01001",
        "ParentAccountId": "01"
      },
      {
        "Id": "4",
        "Code": "01002",
        "Title": "Account 01002",
        "ParentAccountId": "01"
      },
      {
        "Id": "5",
        "Code": "01002001",
        "Title": "Account 01002001",
        "ParentAccountId": "01002"
      }
    ]
    
    function buildTree(obj) {
      // get all top level parents
      let parents = obj.filter((o) => !o.ParentAccountId);
      // loop over the parents and recursively call addChild to populate the tree
      parents.forEach((p) => {
        p.children = addChildren(p, obj);
      });
    
      return parents;
    }
    
    function addChildren(parent, obj) {
      // find all children for this parent
      let children = obj.filter((o) => o.ParentAccountId === parent.Code)
      if (children.length) {
        // loop over any children recursively calling this function to add nested children
        children.forEach((c) => {
          c.children = addChildren(c, obj);
        });
        return children;
      } else {
        return [];
      }
    }
    
    console.log(buildTree(data));

    【讨论】:

      【解决方案4】:

      您可以遍历每个节点并构建一个 child-id 到 child 的映射。

      然后,再次遍历节点,但这次查看 parent-ids 并将节点推送到父节点(如果它是子节点),或者将其添加到根列表中。此响应改编自 here,并添加了自定义密钥配置。

      我还添加了一种方法来删除任何不包含子节点(即叶节点)的对象上的 children 字段。

      console.log(convertListToTree(getDataList(), {
        idKey : 'Code',
        parentIdKey : 'ParentAccountId',
        pruneEmptyChildren : true
      }));
      
      function convertListToTree(list, options) {
        options = Object.assign({
          idKey : 'id',
          parentIdKey : 'parentId',
          childrenKey : 'children',
          pruneEmptyChildren : false
        }, options || {});
        let map = {}, node, roots = [], i;
        for (i = 0; i < list.length; i++) {
          map[list[i][options.idKey]] = i;
          list[i][options.childrenKey] = []; // Attach a "child" reference holder
        }
        for (i = 0; i < list.length; i++) {
          node = list[i];
          if (node[options.parentIdKey] != null) {
            list[map[node[options.parentIdKey]]][options.childrenKey].push(node);
          } else {
            roots.push(node);
          }
        }
        if (options.pruneEmptyChildren) {
          pruneEmptyKeys(roots, options.childrenKey); // Remove empty
        }
        return roots;
      }
      
      function pruneEmptyKeys(tree, childKey) {
        let items = tree[childKey] || tree;
        items.forEach(item => {
          if (item[childKey].length > 0) {
            pruneEmptyKeys(item[childKey], childKey);
          } else {
            delete item[childKey]; // Remove empty child list
          }
        });
      }
      
      function getDataList() {
        return [{
          "Id": "1",
          "Code": "01",
          "Title": "Account 01",
          "ParentAccountId": null
        }, {
          "Id": "2",
          "Code": "02",
          "Title": "Account 02",
          "ParentAccountId": null
        }, {
          "Id": "3",
          "Code": "01001",
          "Title": "Account 01001",
          "ParentAccountId": "01"
        }, {
          "Id": "4",
          "Code": "01002",
          "Title": "Account 01002",
          "ParentAccountId": "01"
        }, {
          "Id": "5",
          "Code": "01002001",
          "Title": "Account 01002001",
          "ParentAccountId": "01002"
        }];
      }
      .as-console-wrapper {
        top: 0;
        max-height: 100% !important;
      }
      &lt;!-- Adapted from: https://stackoverflow.com/a/18018037/1762224 --&gt;

      【讨论】:

        猜你喜欢
        • 2022-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-02
        • 1970-01-01
        • 2018-10-08
        相关资源
        最近更新 更多