在JS中获取JSON,并基于两个键创建嵌套子项

vngu2lb8  于 2023-02-14  发布在  其他
关注(0)|答案(1)|浏览(104)

我使用一个平面JSON文件,并尝试创建一个结构化树,将ParentID与NodeID匹配的相关子节点放置在相关NodeID之下。
但是,如果没有parentID,它应该查看previousSiblingId并将记录放在相关NodeID下面。
我相信我已经很接近了,我能够使它在parentId上工作,但是当我引入previousSiblingId时,它就停止工作了。
这是初始平面文件:
预期结果应为:

[
  {
    "nodeId": "3",
    "name": "Three",
    "parentId": null,
    "previousSiblingId": null,
    "children": []
  },
  {
    "nodeId": "1",
    "name": "One",
    "parentId": null,
    "previousSiblingId": "3",
    "children": [
      {
        "nodeId": "2",
        "name": "Two",
        "parentId": "1",
        "previousSiblingId": null,
        "children": [
          {
            "nodeId": "6",
            "name": "Six",
            "parentId": "2",
            "previousSiblingId": null,
            "children": []
          },
          {
            "nodeId": "4",
            "name": "Four",
            "parentId": "2",
            "previousSiblingId": "6",
            "children": [
              {
                "nodeId": "5",
                "name": "Five",
                "parentId": "4",
                "previousSiblingId": null,
                "children": []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "nodeId": "7",
    "name": "Seven",
    "parentId": null,
    "previousSiblingId": "1",
    "children": [
      {
        "nodeId": "8",
        "name": "Eight",
        "parentId": "7",
        "previousSiblingId": null,
        "children": []
      }
    ]
  }
]

我目前的结果是:

[
  {
    "nodeId": "3",
    "name": "Three",
    "parentId": null,
    "previousSiblingId": null,
    "children": []
  },
  {
    "nodeId": "7",
    "name": "Seven",
    "parentId": null,
    "previousSiblingId": "1",
    "children": [
      {
        "nodeId": "8",
        "name": "Eight",
        "parentId": "7",
        "previousSiblingId": null,
        "children": []
      }
    ]
  },
  {
    "nodeId": "1",
    "name": "One",
    "parentId": null,
    "previousSiblingId": "3",
    "children": [
      {
        "nodeId": "2",
        "name": "Two",
        "parentId": "1",
        "previousSiblingId": null,
        "children": [
          {
            "nodeId": "4",
            "name": "Four",
            "parentId": "2",
            "previousSiblingId": "6",
            "children": [
              {
                "nodeId": "5",
                "name": "Five",
                "parentId": "4",
                "previousSiblingId": null,
                "children": []
              }
            ]
          },
          {
            "nodeId": "6",
            "name": "Six",
            "parentId": "2",
            "previousSiblingId": null,
            "children": []
          }
        ]
      }
    ]
  }
]

我错过了什么?

<html>
<pre id="json"></pre>
<script type="text/javascript">

const data = [{
   "nodeId": "4",
    "name": "Four",
    "parentId": "2",
    "previousSiblingId": "6"
    },
    {
      "nodeId": "8",
    "name": "Eight",
    "parentId": "7",
    "previousSiblingId": null
    },
    {
    "nodeId": "2",
    "name": "Two",
    "parentId": "1",
    "previousSiblingId": null
  },
  {
    "nodeId": "6",
    "name": "Six",
    "parentId": "2",
    "previousSiblingId": null
  },
  {
    "nodeId": "3",
    "name": "Three",
    "parentId": null,
    "previousSiblingId": null
  },
  {
    "nodeId": "5",
    "name": "Five",
    "parentId": "4",
    "previousSiblingId": null
  },
  {
    "nodeId": "7",
    "name": "Seven",
    "parentId": null,
    "previousSiblingId": "1"
  },
  {
    "nodeId": "1",
    "name": "One",
    "parentId": null,
    "previousSiblingId": "3"
  }
  ];

  const getParentDeep = (arr, targetId) => arr.find(({ nodeId }) => nodeId === targetId)
    ?? arr.flatMap(({ children }) => getParentDeep(children, targetId))
    .filter(e => e)
    .at(0);

const result = data
.sort(({ parentId: a }, { parentId: b }) => a - b, ({ previousSiblingId: c }, { previousSiblingId: d }) => c - d)

  .reduce((acc, { nodeId, name, parentId, previousSiblingId }) => {
    const obj = { nodeId, name: name, parentId: parentId, previousSiblingId: previousSiblingId, children: [] };
    const parentObj = getParentDeep(acc, parentId);
    const previousSiblingObj = getParentDeep(acc, previousSiblingId);
    if (parentObj) parentObj.children.push(obj)
    else
    if (previousSiblingObj) previousSiblingObj.children.push(obj);
    else
    acc.push(obj);
    return acc;
}, []);

//
console.log(result);

//Output the new JSON to the screen
    document.getElementById("json").textContent = JSON.stringify(result, undefined, 2);

</script>

</html>
inb24sb2

inb24sb21#

你可以用一个对象的单循环方法来保持所有引用,其中part指向child,child指向parent,最后只取值为null的child作为parent。
如果child包含两个以上的项,则对该数组进行排序。

const
    data = [{ nodeId: "4", name: "Four", parentId: "2", previousSiblingId: "6" }, { nodeId: "8", name: "Eight", parentId: "7", previousSiblingId: null }, { nodeId: "2", name: "Two", parentId: "1", previousSiblingId: null }, { nodeId: "6", name: "Six", parentId: "2", previousSiblingId: null }, { nodeId: "3", name: "Three", parentId: null, previousSiblingId: null }, { nodeId: "5", name: "Five", parentId: "4", previousSiblingId: null }, { nodeId: "7", name: "Seven", parentId: null, previousSiblingId: "1" }, { nodeId: "1", name: "One", parentId: null, previousSiblingId: "3" }],
    tree = function (data, root) {
        const
            sort = array => {
                if (array.length < 2) return;
                let node = array.find(o => o.previousSiblingId === null)?.nodeId,
                    i = 0;

                while (i < array.length) {
                    if (array[i].nodeId !== node) {
                        const j = array.findIndex(o => o.nodeId === node);
                        array.splice(i, 0, ...array.splice(j, 1));
                    }
                    node = next[node];
                    i++;
                }
            },
            empty = { nodeId: undefined, name: undefined, parentId: undefined, previousSiblingId: undefined },
            next = {},
            t = {};

        data.forEach(o => {
            Object.assign(t[o.nodeId] = t[o.nodeId] || { ...empty }, o);

            t[o.parentId] ??= { ...empty };
            t[o.parentId].children ??= [];
            t[o.parentId].children.push(t[o.nodeId]);

            if (o.previousSiblingId !== null) next[o.previousSiblingId] = o.nodeId;
            sort(t[o.parentId].children);
        });

        return t[root].children;
    }(data, null);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

相关问题