采用JS中的JSON,并基于两个键创建嵌套子元素。

huangapple go评论70阅读模式
英文:

Take a JSON in JS and create the nested children based on two keys

问题

我正在尝试将一个扁平的JSON文件转化为一个结构化的树,将具有匹配NodeID的ParentID的相关子项放置在相应的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": []
          }
        ]
      }
    ]
  }
]

我漏掉了什么?

英文:

I am taking a flat JSON file and trying to create a structured tree which places the relevant children, whose ParentID matches a NodeID, underneath the relevant NodeID.

However, if there is no parentID, it should look at the previousSiblingId and place the record underneath the relevant NodeID.

I believe I am close, I am able to make it work on the parentId but when I introduce the previousSiblingId it stops working.

This is the initial flat file:

The expected result should be:

[
  {
    "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": []
      }
    ]
  }
]

my current result is:

[
  {
    "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": []
          }
        ]
      }
    ]
  }
]

What have I missed?

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

答案1

得分: 1

你可以使用一个对象采用单循环方法,将所有引用与子代和父代相关联。最后只获取具有 null 值作为父级的子代。

如果子代包含超过两个项目,对该数组进行排序。

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; }
英文:

You could take a single loop approach with an object to keep all references with part to children and children to parent. At the end take only the children which have null value as parent.

If child contains more than two items sort this array.

<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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 &lt; array.length) {
if (array[i].nodeId !== node) {
const j = array.findIndex(o =&gt; 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 =&gt; {
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);

<!-- language: lang-css -->
.as-console-wrapper { max-height: 100% !important; top: 0; }
<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月9日 02:15:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75390090.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定